You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2015/05/20 14:22:13 UTC

wicket git commit: WICKET-5910 Do not intercept the protected methods with CGLib.

Repository: wicket
Updated Branches:
  refs/heads/master 31f3acb0d -> 077e1c3d5


WICKET-5910 Do not intercept the protected methods with CGLib.


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/077e1c3d
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/077e1c3d
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/077e1c3d

Branch: refs/heads/master
Commit: 077e1c3d54d044ccfe7b56cc4decf4baf2cc6717
Parents: 31f3acb
Author: Guillaume Smet <gu...@gmail.com>
Authored: Tue May 19 23:15:02 2015 +0200
Committer: Guillaume Smet <gu...@gmail.com>
Committed: Wed May 20 13:24:34 2015 +0200

----------------------------------------------------------------------
 .../wicket/proxy/LazyInitProxyFactory.java      | 53 +++++++++++++++++++-
 1 file changed, 51 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/077e1c3d/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java
----------------------------------------------------------------------
diff --git a/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java b/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java
index b9ec468..5f0f101 100644
--- a/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java
+++ b/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java
@@ -21,15 +21,19 @@ import java.io.Serializable;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import java.util.Arrays;
 import java.util.List;
 
 import net.sf.cglib.core.DefaultNamingPolicy;
 import net.sf.cglib.core.Predicate;
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.CallbackFilter;
 import net.sf.cglib.proxy.Enhancer;
 import net.sf.cglib.proxy.MethodInterceptor;
 import net.sf.cglib.proxy.MethodProxy;
+import net.sf.cglib.proxy.NoOp;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.WicketRuntimeException;
@@ -111,6 +115,9 @@ public class LazyInitProxyFactory
 		Float.class, double.class, Double.class, char.class, Character.class, boolean.class,
 		Boolean.class);
 
+	private static final int CGLIB_CALLBACK_NO_OVERRIDE = 0;
+	private static final int CGLIB_CALLBACK_HANDLER = 1;
+
 	/**
 	 * Create a lazy init proxy for the specified type. The target object will be located using the
 	 * provided locator upon first method invocation.
@@ -159,12 +166,17 @@ public class LazyInitProxyFactory
 		{
 			CGLibInterceptor handler = new CGLibInterceptor(type, locator);
 
+			Callback[] callbacks = new Callback[2];
+			callbacks[CGLIB_CALLBACK_NO_OVERRIDE] = new SerializableNoOpCallback();
+			callbacks[CGLIB_CALLBACK_HANDLER] = handler;
+
 			Enhancer e = new Enhancer();
 			e.setClassLoader(resolveClassLoader());
 			e.setInterfaces(new Class[] { Serializable.class, ILazyInitProxy.class,
 					IWriteReplace.class });
 			e.setSuperclass(type);
-			e.setCallback(handler);
+			e.setCallbackFilter(new NoOpForProtectedMethodsCGLibCallbackFilter());
+			e.setCallbacks(callbacks);
 			e.setNamingPolicy(WicketNamingPolicy.INSTANCE);
 
 			return e.create();
@@ -252,7 +264,7 @@ public class LazyInitProxyFactory
 
 	/**
 	 * Method interceptor for proxies representing concrete object not backed by an interface. These
-	 * proxies are representing by cglib proxies.
+	 * proxies are represented by cglib proxies.
 	 * 
 	 * @author Igor Vaynberg (ivaynberg)
 	 * 
@@ -349,6 +361,43 @@ public class LazyInitProxyFactory
 	}
 
 	/**
+	 * Serializable implementation of the NoOp callback.
+	 */
+	public static class SerializableNoOpCallback implements NoOp, Serializable
+	{
+		private static final long serialVersionUID = 1L;
+	}
+
+	/**
+	 * CGLib callback filter which does not intercept protected methods.
+	 * 
+	 * Protected methods need to be called with invokeSuper() instead of invoke().
+	 * When invoke() is called on a protected method, it throws an "IllegalArgumentException:
+	 * Protected method" exception.
+	 * That being said, we do not need to intercept the protected methods so this callback filter
+	 * is designed to use a NoOp callback for protected methods.
+	 * 
+	 * @see <a href="http://comments.gmane.org/gmane.comp.java.cglib.devel/720">Discussion about
+	 * this very issue in Spring AOP</a>
+	 * @see <a href="https://github.com/wicketstuff/core/wiki/SpringReference">The WicketStuff
+	 * SpringReference project which worked around this issue</a>
+	 */
+	private static class NoOpForProtectedMethodsCGLibCallbackFilter implements CallbackFilter
+	{
+		@Override
+		public int accept(Method method) {
+			if (Modifier.isProtected(method.getModifiers()))
+			{
+				return CGLIB_CALLBACK_NO_OVERRIDE;
+			}
+			else
+			{
+				return CGLIB_CALLBACK_HANDLER;
+			}
+		}
+	}
+
+	/**
 	 * Invocation handler for proxies representing interface based object. For interface backed
 	 * objects dynamic jdk proxies are used.
 	 *