|
From: <hib...@li...> - 2006-07-20 17:27:33
|
Author: scottmarlownovell
Date: 2006-07-20 13:27:30 -0400 (Thu, 20 Jul 2006)
New Revision: 10126
Modified:
trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java
Log:
Fix for HHH-1293. Switched to using InvocationHandler.
Modified: trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2006-07-19 14:11:50 UTC (rev 10125)
+++ trunk/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2006-07-20 17:27:30 UTC (rev 10126)
@@ -4,16 +4,19 @@
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
-import net.sf.cglib.proxy.Factory;
-import net.sf.cglib.proxy.MethodInterceptor;
-import net.sf.cglib.proxy.MethodProxy;
+import net.sf.cglib.proxy.InvocationHandler;
import net.sf.cglib.proxy.NoOp;
import org.hibernate.HibernateException;
+import org.hibernate.LazyInitializationException;
import org.hibernate.proxy.pojo.BasicLazyInitializer;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.engine.SessionImplementor;
@@ -25,11 +28,8 @@
/**
* A <tt>LazyInitializer</tt> implemented using the CGLIB bytecode generation library
*/
-public final class CGLIBLazyInitializer extends BasicLazyInitializer implements MethodInterceptor {
+public final class CGLIBLazyInitializer extends BasicLazyInitializer implements InvocationHandler {
-
- private static final Class[] CALLBACK_TYPES = new Class[]{ MethodInterceptor.class,NoOp.class };
-
private static final CallbackFilter FINALIZE_FILTER = new CallbackFilter() {
public int accept(Method method) {
if ( method.getParameterTypes().length == 0 && method.getName().equals("finalize") ){
@@ -49,7 +49,7 @@
final Method setIdentifierMethod, AbstractComponentType componentIdType,
final Serializable id, final SessionImplementor session) throws HibernateException {
// note: interfaces is assumed to already contain HibernateProxy.class
-
+
try {
final CGLIBLazyInitializer instance = new CGLIBLazyInitializer(
entityName,
@@ -59,16 +59,13 @@
getIdentifierMethod,
setIdentifierMethod,
componentIdType,
- session
+ session
);
-
- final HibernateProxy proxy = (HibernateProxy) Enhancer.create(
- interfaces.length == 1 ? persistentClass : null,
- interfaces,
- FINALIZE_FILTER,
- new Callback[]{ instance, NoOp.INSTANCE }
- );
-
+
+ final HibernateProxy proxy;
+ Class factory = getProxyFactory(persistentClass, interfaces);
+ Enhancer.registerCallbacks(factory, new Callback[]{ instance, null });
+ proxy = (HibernateProxy)factory.newInstance();
instance.constructed = true;
return proxy;
}
@@ -84,7 +81,7 @@
final Method getIdentifierMethod, final Method setIdentifierMethod,
final AbstractComponentType componentIdType, final Serializable id,
final SessionImplementor session) throws HibernateException {
-
+
final CGLIBLazyInitializer instance = new CGLIBLazyInitializer(
entityName,
persistentClass,
@@ -93,17 +90,17 @@
getIdentifierMethod,
setIdentifierMethod,
componentIdType,
- session
+ session
);
-
+
final HibernateProxy proxy;
try {
- proxy = (HibernateProxy) factory.newInstance();
+ Enhancer.registerCallbacks(factory, new Callback[]{ instance, null });
+ proxy = (HibernateProxy)factory.newInstance();
}
catch (Exception e) {
throw new HibernateException( "CGLIB Enhancement failed: " + persistentClass.getName(), e );
}
- ( (Factory) proxy ).setCallback( 0, instance );
instance.constructed = true;
return proxy;
@@ -111,28 +108,17 @@
public static Class getProxyFactory(Class persistentClass, Class[] interfaces)
throws HibernateException {
- // note: interfaces is assumed to already contain HibernateProxy.class
-
- try {
-
- Enhancer en = new Enhancer();
- en.setUseCache( false );
- en.setInterceptDuringConstruction( false );
-
- en.setCallbackTypes( CALLBACK_TYPES );
- en.setCallbackFilter( FINALIZE_FILTER );
-
- en.setSuperclass( interfaces.length == 1 ? persistentClass : null );
- en.setInterfaces( interfaces );
-
- return en.createClass();
-
- }
- catch (Throwable t) {
- LogFactory.getLog( BasicLazyInitializer.class )
- .error( "CGLIB Enhancement failed: " + persistentClass.getName(), t );
- throw new HibernateException( "CGLIB Enhancement failed: " + persistentClass.getName(), t );
- }
+ Enhancer e = new Enhancer();
+ e.setSuperclass( interfaces.length == 1 ? persistentClass : null );
+ e.setInterfaces(interfaces);
+ e.setCallbackTypes(new Class[]{
+ InvocationHandler.class,
+ NoOp.class,
+ });
+ e.setCallbackFilter(FINALIZE_FILTER);
+ e.setUseFactory(false);
+ e.setInterceptDuringConstruction( false );
+ return e.createClass();
}
private CGLIBLazyInitializer(final String entityName, final Class persistentClass,
@@ -146,48 +132,80 @@
getIdentifierMethod,
setIdentifierMethod,
componentIdType,
- session
+ session
);
this.interfaces = interfaces;
}
- public Object intercept(final Object proxy, final Method method, final Object[] args,
- final MethodProxy methodProxy) throws Throwable {
+ private static boolean isCastable(Class caster, Class castee) {
+ if ( castee.equals( caster ) ) {
+ return true;
+ }
+ List list = addCheckingTypes( caster, new ArrayList() );
+ for ( Iterator iter = list.iterator(); iter.hasNext(); ) {
+ Class cl = ( Class ) iter.next();
+ if ( castee.equals( cl ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static List addCheckingTypes(final Class type, final List list) {
+ Class superclass = type.getSuperclass();
+ if ( superclass != null ) {
+ list.add( superclass );
+ addCheckingTypes( superclass, list );
+ }
+ Class[] interfaces = type.getInterfaces();
+ for ( int i = 0; i < interfaces.length; ++i ) {
+ list.add( interfaces[i] );
+ addCheckingTypes( interfaces[i], list );
+ }
+ return list;
+ }
+
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if ( constructed ) {
-
Object result = invoke( method, args, proxy );
if ( result == INVOKE_IMPLEMENTATION ) {
Object target = getImplementation();
final Object returnValue;
- if ( ReflectHelper.isPublic( persistentClass, method ) ) {
- returnValue = methodProxy.invoke( target, args );
- }
- else {
- if ( !method.isAccessible() ) method.setAccessible( true );
- try {
+ try {
+ if ( ReflectHelper.isPublic( persistentClass, method ) ) {
+ if ( !isCastable(
+ target.getClass(), method
+ .getDeclaringClass()
+ ) ) {
+ throw new ClassCastException(
+ target.getClass()
+ .getName()
+ );
+ }
returnValue = method.invoke( target, args );
}
- catch (InvocationTargetException ite) {
- throw ite.getTargetException();
+ else {
+ if ( !method.isAccessible() ) method.setAccessible( true );
+ returnValue = method.invoke( target, args );
}
+ return returnValue == target ? proxy : returnValue;
}
- return returnValue == target ? proxy : returnValue;
+ catch (InvocationTargetException ite) {
+ throw ite.getTargetException();
+ }
}
else {
return result;
}
-
}
else {
-
// while constructor is running
if ( method.getName().equals( "getHibernateLazyInitializer" ) ) {
return this;
}
else {
- return methodProxy.invokeSuper( proxy, args );
+ throw new LazyInitializationException("unexpected case hit, method=" + method.getName());
}
-
}
}
|