From: <hib...@li...> - 2006-07-24 19:44:00
|
Author: scottmarlownovell Date: 2006-07-24 15:43:49 -0400 (Mon, 24 Jul 2006) New Revision: 10146 Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java Log: Fix for HHH-1293. Use InvocationHandler instead of MethodInterceptor. Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java =================================================================== --- branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2006-07-24 18:51:28 UTC (rev 10145) +++ branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2006-07-24 19:43:49 UTC (rev 10146) @@ -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") ){ @@ -62,13 +62,10 @@ 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; } @@ -98,12 +95,12 @@ final HibernateProxy proxy; try { + 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, @@ -151,43 +137,75 @@ 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; + try { if ( ReflectHelper.isPublic( persistentClass, method ) ) { - returnValue = methodProxy.invoke( target, args ); + if ( !isCastable( + target.getClass(), method + .getDeclaringClass() + ) ) { + throw new ClassCastException( + target.getClass() + .getName() + ); + } + returnValue = method.invoke( target, args ); } else { if ( !method.isAccessible() ) method.setAccessible( true ); - try { returnValue = method.invoke( target, args ); } + return returnValue == target ? proxy : returnValue; + } catch (InvocationTargetException ite) { throw ite.getTargetException(); } } - return returnValue == target ? proxy : returnValue; - } 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()); } - } } |