Source code: org/hibernate/bytecode/cglib/ProxyFactoryFactoryImpl.java
1 package org.hibernate.bytecode.cglib;
2
3 import org.hibernate.bytecode.ProxyFactoryFactory;
4 import org.hibernate.bytecode.BasicProxyFactory;
5 import org.hibernate.proxy.ProxyFactory;
6 import org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory;
7 import org.hibernate.AssertionFailure;
8 import org.hibernate.HibernateException;
9 import net.sf.cglib.proxy.Enhancer;
10 import net.sf.cglib.proxy.CallbackFilter;
11 import net.sf.cglib.proxy.MethodInterceptor;
12 import net.sf.cglib.proxy.MethodProxy;
13 import net.sf.cglib.proxy.NoOp;
14 import net.sf.cglib.proxy.Callback;
15 import net.sf.cglib.proxy.Factory;
16
17 import java.lang.reflect.Method;
18 import java.util.HashMap;
19
20 /**
21 * A factory for CGLIB-based {@link ProxyFactory} instances.
22 *
23 * @author Steve Ebersole
24 */
25 public class ProxyFactoryFactoryImpl implements ProxyFactoryFactory {
26
27 /**
28 * Builds a CGLIB-based proxy factory.
29 *
30 * @return a new CGLIB-based proxy factory.
31 */
32 public ProxyFactory buildProxyFactory() {
33 return new CGLIBProxyFactory();
34 }
35
36 public BasicProxyFactory buildBasicProxyFactory(Class superClass, Class[] interfaces) {
37 return new BasicProxyFactoryImpl( superClass, interfaces );
38 }
39
40 public static class BasicProxyFactoryImpl implements BasicProxyFactory {
41 private final Class proxyClass;
42 private final Factory factory;
43
44 public BasicProxyFactoryImpl(Class superClass, Class[] interfaces) {
45 if ( superClass == null && ( interfaces == null || interfaces.length < 1 ) ) {
46 throw new AssertionFailure( "attempting to build proxy without any superclass or interfaces" );
47 }
48
49 Enhancer en = new Enhancer();
50 en.setUseCache( false );
51 en.setInterceptDuringConstruction( false );
52 en.setUseFactory( true );
53 en.setCallbackTypes( CALLBACK_TYPES );
54 en.setCallbackFilter( FINALIZE_FILTER );
55 if ( superClass != null ) {
56 en.setSuperclass( superClass );
57 }
58 if ( interfaces != null && interfaces.length > 0 ) {
59 en.setInterfaces( interfaces );
60 }
61 proxyClass = en.createClass();
62 try {
63 factory = ( Factory ) proxyClass.newInstance();
64 }
65 catch ( Throwable t ) {
66 throw new HibernateException( "Unable to build CGLIB Factory instance" );
67 }
68 }
69
70 public Object getProxy() {
71 try {
72 return factory.newInstance(
73 new Callback[] { new PassThroughInterceptor( proxyClass.getName() ), NoOp.INSTANCE }
74 );
75 }
76 catch ( Throwable t ) {
77 throw new HibernateException( "Unable to instantiate proxy instance" );
78 }
79 }
80 }
81
82 private static final CallbackFilter FINALIZE_FILTER = new CallbackFilter() {
83 public int accept(Method method) {
84 if ( method.getParameterTypes().length == 0 && method.getName().equals("finalize") ){
85 return 1;
86 }
87 else {
88 return 0;
89 }
90 }
91 };
92
93 private static final Class[] CALLBACK_TYPES = new Class[] { MethodInterceptor.class, NoOp.class };
94
95 private static class PassThroughInterceptor implements MethodInterceptor {
96 private HashMap data = new HashMap();
97 private final String proxiedClassName;
98
99 public PassThroughInterceptor(String proxiedClassName) {
100 this.proxiedClassName = proxiedClassName;
101 }
102
103 public Object intercept(
104 Object obj,
105 Method method,
106 Object[] args,
107 MethodProxy proxy) throws Throwable {
108 String name = method.getName();
109 if ( "toString".equals( name ) ) {
110 return proxiedClassName + "@" + System.identityHashCode( obj );
111 }
112 else if ( "equals".equals( name ) ) {
113 return args[0] instanceof Factory && ( ( Factory ) args[0] ).getCallback( 0 ) == this
114 ? Boolean.TRUE
115 : Boolean.FALSE;
116 }
117 else if ( "hashCode".equals( name ) ) {
118 return new Integer( System.identityHashCode( obj ) );
119 }
120 boolean hasGetterSignature = method.getParameterTypes().length == 0 && method.getReturnType() != null;
121 boolean hasSetterSignature = method.getParameterTypes().length == 1 && ( method.getReturnType() == null || method.getReturnType() == void.class );
122 if ( name.startsWith( "get" ) && hasGetterSignature ) {
123 String propName = name.substring( 3 );
124 return data.get( propName );
125 }
126 else if ( name.startsWith( "is" ) && hasGetterSignature ) {
127 String propName = name.substring( 2 );
128 return data.get( propName );
129 }
130 else if ( name.startsWith( "set" ) && hasSetterSignature) {
131 String propName = name.substring( 3 );
132 data.put( propName, args[0] );
133 return null;
134 }
135 else {
136 // todo : what else to do here?
137 return null;
138 }
139 }
140 }
141 }