Source code: org/hibernate/bytecode/cglib/BytecodeProviderImpl.java
1 package org.hibernate.bytecode.cglib;
2
3 import java.lang.reflect.Modifier;
4
5 import net.sf.cglib.beans.BulkBean;
6 import net.sf.cglib.beans.BulkBeanException;
7 import net.sf.cglib.reflect.FastClass;
8 import net.sf.cglib.transform.ClassFilter;
9 import net.sf.cglib.transform.ClassTransformer;
10 import net.sf.cglib.transform.ClassTransformerFactory;
11 import net.sf.cglib.transform.TransformingClassLoader;
12 import net.sf.cglib.transform.impl.InterceptFieldFilter;
13 import net.sf.cglib.transform.impl.InterceptFieldTransformer;
14 import org.apache.commons.logging.Log;
15 import org.apache.commons.logging.LogFactory;
16 import org.hibernate.bytecode.BytecodeProvider;
17 import org.hibernate.bytecode.ProxyFactoryFactory;
18 import org.hibernate.bytecode.ReflectionOptimizer;
19 import org.hibernate.util.StringHelper;
20 import org.objectweb.asm.Type;
21
22 /**
23 * Bytecode provider implementation for CGLIB.
24 *
25 * @author Steve Ebersole
26 */
27 public class BytecodeProviderImpl implements BytecodeProvider {
28
29 private static final Log log = LogFactory.getLog( BytecodeProviderImpl.class );
30
31 public ProxyFactoryFactory getProxyFactoryFactory() {
32 return new ProxyFactoryFactoryImpl();
33 }
34
35 public ReflectionOptimizer getReflectionOptimizer(
36 Class clazz,
37 String[] getterNames,
38 String[] setterNames,
39 Class[] types) {
40 FastClass fastClass;
41 BulkBean bulkBean;
42 try {
43 fastClass = FastClass.create( clazz );
44 bulkBean = BulkBean.create( clazz, getterNames, setterNames, types );
45 if ( !clazz.isInterface() && !Modifier.isAbstract( clazz.getModifiers() ) ) {
46 if ( fastClass == null ) {
47 bulkBean = null;
48 }
49 else {
50 //test out the optimizer:
51 Object instance = fastClass.newInstance();
52 bulkBean.setPropertyValues( instance, bulkBean.getPropertyValues( instance ) );
53 }
54 }
55 }
56 catch( Throwable t ) {
57 fastClass = null;
58 bulkBean = null;
59 String message = "reflection optimizer disabled for: " +
60 clazz.getName() +
61 " [" +
62 StringHelper.unqualify( t.getClass().getName() ) +
63 ": " +
64 t.getMessage();
65
66 if (t instanceof BulkBeanException ) {
67 int index = ( (BulkBeanException) t ).getIndex();
68 if (index >= 0) {
69 message += " (property " + setterNames[index] + ")";
70 }
71 }
72
73 log.debug( message );
74 }
75
76 if ( fastClass != null && bulkBean != null ) {
77 return new ReflectionOptimizerImpl(
78 new InstantiationOptimizerAdapter( fastClass ),
79 new AccessOptimizerAdapter( bulkBean, clazz )
80 );
81 }
82 else {
83 return null;
84 }
85 }
86
87 public ClassLoader generateDynamicFieldInterceptionClassLoader(
88 ClassLoader parent,
89 String[] classpath,
90 String[] packages) {
91 return new TransformingClassLoader(
92 parent,
93 new ClassLoaderClassFilter( packages ),
94 new ClassTransformerFactory() {
95 public ClassTransformer newInstance() {
96 return new InterceptFieldTransformer(
97 new InterceptFieldFilter() {
98 public boolean acceptRead(Type owner, String name) {
99 return true;
100 }
101 public boolean acceptWrite(Type owner, String name) {
102 return true;
103 }
104 }
105 );
106 }
107 }
108 );
109 }
110
111 public org.hibernate.bytecode.ClassTransformer getEntityClassTransformer(
112 String[] packages, String[] classes
113 ) {
114 return new CglibClassTransformer( packages, classes );
115 }
116
117 public void releaseDynamicFieldInterceptionClassLoader(ClassLoader classLoader) {
118 }
119
120 private static class ClassLoaderClassFilter implements ClassFilter {
121 private final String[] packages;
122
123 public ClassLoaderClassFilter(String[] packages) {
124 this.packages = packages;
125 }
126
127 public boolean accept(String className) {
128 if ( packages == null ) {
129 return true;
130 }
131 else {
132 for ( int i = 0; i < packages.length; i++ ) {
133 if ( className.startsWith( packages[i] ) ) {
134 return true;
135 }
136 }
137 return false;
138 }
139 }
140 }
141 }