1 //$Id: CGLIBLazyInitializer.java,v 1.9 2005/03/21 16:08:28 oneovthafew Exp $
2 package org.hibernate.proxy;
3
4 import java.io.Serializable;
5 import java.lang.reflect.Method;
6
7 import net.sf.cglib.proxy.Enhancer;
8 import net.sf.cglib.proxy.Factory;
9 import net.sf.cglib.proxy.MethodInterceptor;
10 import net.sf.cglib.proxy.MethodProxy;
11 import org.hibernate.HibernateException;
12 import org.hibernate.engine.SessionImplementor;
13 import org.hibernate.type.AbstractComponentType;
14 import org.hibernate.util.ReflectHelper;
15
16 import org.apache.commons.logging.LogFactory;
17
18
19 /**
20 * A <tt>LazyInitializer</tt> implemented using the CGLIB bytecode generation library
21 */
22 public final class CGLIBLazyInitializer extends BasicLazyInitializer implements MethodInterceptor {
23
24 private Class[] interfaces;
25 private boolean constructed = false;
26
27 static HibernateProxy getProxy(
28 final String entityName,
29 final Class persistentClass,
30 final Class[] interfaces,
31 final Method getIdentifierMethod,
32 final Method setIdentifierMethod,
33 AbstractComponentType componentIdType,
34 final Serializable id,
35 final SessionImplementor session)
36 throws HibernateException {
37 //note: interfaces is assumed to already contain HibernateProxy.class
38 try {
39 final CGLIBLazyInitializer instance = new CGLIBLazyInitializer(
40 entityName,
41 persistentClass,
42 interfaces,
43 id,
44 getIdentifierMethod,
45 setIdentifierMethod,
46 componentIdType,
47 session
48 );
49 final HibernateProxy proxy = (HibernateProxy) Enhancer.create(
50 (interfaces.length==1) ?
51 persistentClass :
52 null,
53 interfaces,
54 instance
55 );
56 instance.constructed = true;
57 return proxy;
58 }
59 catch (Throwable t) {
60 LogFactory.getLog(BasicLazyInitializer.class).error("CGLIB Enhancement failed: " + entityName, t);
61 throw new HibernateException( "CGLIB Enhancement failed: " + entityName, t );
62 }
63 }
64
65 public static HibernateProxy getProxy(
66 final Factory factory,
67 final String entityName,
68 final Class persistentClass,
69 final Class[] interfaces,
70 final Method getIdentifierMethod,
71 final Method setIdentifierMethod,
72 AbstractComponentType componentIdType,
73 final Serializable id,
74 final SessionImplementor session)
75 throws HibernateException {
76 final CGLIBLazyInitializer instance = new CGLIBLazyInitializer(
77 entityName,
78 persistentClass,
79 interfaces,
80 id,
81 getIdentifierMethod,
82 setIdentifierMethod,
83 componentIdType,
84 session
85 );
86 final HibernateProxy proxy = (HibernateProxy) factory.newInstance(instance);
87 instance.constructed = true;
88 return proxy;
89 }
90
91 public static Factory getProxyFactory(Class persistentClass, Class[] interfaces) throws HibernateException {
92 //note: interfaces is assumed to already contain HibernateProxy.class
93 try {
94 return (Factory) Enhancer.create(
95 (interfaces.length==1) ?
96 persistentClass :
97 null,
98 interfaces,
99 NULL_METHOD_INTERCEPTOR
100 );
101 }
102 catch (Throwable t) {
103 LogFactory.getLog(BasicLazyInitializer.class).error(
104 "CGLIB Enhancement failed: " +
105 persistentClass.getName(),
106 t
107 );
108 throw new HibernateException( "CGLIB Enhancement failed: " + persistentClass.getName(), t );
109 }
110 }
111
112 private CGLIBLazyInitializer(
113 final String entityName,
114 final Class persistentClass,
115 final Class[] interfaces,
116 final Serializable id,
117 final Method getIdentifierMethod,
118 final Method setIdentifierMethod,
119 AbstractComponentType componentIdType,
120 final SessionImplementor session) {
121 super(entityName, persistentClass, id, getIdentifierMethod, setIdentifierMethod, componentIdType, session);
122 this.interfaces = interfaces;
123 }
124
125 public Object intercept(
126 final Object proxy,
127 final Method method,
128 final Object[] args,
129 final MethodProxy methodProxy)
130 throws Throwable {
131 if (constructed) {
132 Object result = invoke(method, args, proxy);
133 if (result==INVOKE_IMPLEMENTATION) {
134 Object target = getImplementation();
135 final Object returnValue;
136 if ( ReflectHelper.isPublic(persistentClass, method) ) {
137 returnValue = methodProxy.invoke(target, args);
138 }
139 else {
140 if ( !method.isAccessible() ) method.setAccessible(true);
141 returnValue = method.invoke(target, args);
142 }
143 return returnValue==target ? proxy : returnValue;
144 }
145 else {
146 return result;
147 }
148 }
149 else {
150 //while constructor is running
151 if( method.getName().equals("getHibernateLazyInitializer") ) {
152 return this;
153 }
154 else {
155 return methodProxy.invokeSuper(proxy, args);
156 }
157 }
158 }
159
160 protected Object serializableProxy() {
161 return new SerializableProxy(
162 getEntityName(),
163 persistentClass,
164 interfaces,
165 getIdentifier(),
166 getIdentifierMethod,
167 setIdentifierMethod,
168 componentIdType
169 );
170 }
171
172 private static final MethodInterceptor NULL_METHOD_INTERCEPTOR = new MethodInterceptor() {
173 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
174 return proxy.invokeSuper(obj, args);
175 }
176 };
177 }