Repository: wicket
Updated Branches:
  refs/heads/master 312bddbc4 -> f295636ab


WICKET-6353: override resolveProxyClass to lookup classes in Wicket's 
ClassResolver


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

Branch: refs/heads/master
Commit: f295636ab57bcb13496ea5e700784a6dc89098f5
Parents: 312bddb
Author: Emond Papegaaij <[email protected]>
Authored: Wed Apr 5 14:54:28 2017 +0200
Committer: Emond Papegaaij <[email protected]>
Committed: Thu Apr 13 08:50:11 2017 +0200

----------------------------------------------------------------------
 .../wicket/serialize/java/JavaSerializer.java   | 136 +++++++++++++++++--
 1 file changed, 124 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/f295636a/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
 
b/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
index 1ca239b..0767f1c 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
@@ -25,6 +25,10 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamClass;
 import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.ThreadContext;
@@ -188,34 +192,58 @@ public class JavaSerializer implements ISerializer
                protected Class<?> resolveClass(ObjectStreamClass desc) throws 
IOException,
                        ClassNotFoundException
                {
-                       String className = desc.getName();
-
                        try
                        {
                                return super.resolveClass(desc);
                        }
-                       catch (ClassNotFoundException ex1)
+                       catch (ClassNotFoundException cnfEx)
                        {
                                // ignore this exception.
-                               log.debug("Class not found by the object 
outputstream itself, trying the IClassResolver");
+                               log.debug(
+                                       "Class not found by the object 
outputstream itself, trying the IClassResolver");
+
+                               Class< ? > candidate = 
resolveClassInWicket(desc.getName());
+                               if (candidate == null)
+                               {
+                                       throw cnfEx;
+                               }
+                               return candidate;
                        }
+               }
 
+               /*
+                * resolves a class by name, first using the default 
Class.forName, but looking in the
+                * Wicket ClassResolvers as well.
+                */
+               private Class<?> resolveClassByName(String className, 
ClassLoader latestUserDefined)
+                       throws ClassNotFoundException
+               {
+                       try
+                       {
+                               return Class.forName(className, false, 
latestUserDefined);
+                       }
+                       catch (ClassNotFoundException cnfEx)
+                       {
+                               Class<?> ret = resolveClassInWicket(className);
+                               if (ret == null)
+                                       throw cnfEx;
+                               return ret;
+                       }
+               }
 
-                       Class<?> candidate = null;
+               /*
+                * Resolves a class from Wicket's ClassResolver
+                */
+               private Class<?> resolveClassInWicket(String className) throws 
ClassNotFoundException
+               {
+                       Class<?> candidate;
                        try
                        {
-                               // Can the application always be taken??
-                               // Should be if serialization happened in 
thread with application set
-                               // (WICKET-2195)
                                Application application = Application.get();
                                ApplicationSettings applicationSettings = 
application.getApplicationSettings();
                                IClassResolver classResolver = 
applicationSettings.getClassResolver();
 
                                candidate = 
classResolver.resolveClass(className);
-                               if (candidate == null)
-                               {
-                                       candidate = super.resolveClass(desc);
-                               }
                        }
                        catch (WicketRuntimeException ex)
                        {
@@ -223,10 +251,94 @@ public class JavaSerializer implements ISerializer
                                {
                                        throw 
(ClassNotFoundException)ex.getCause();
                                }
+                               else
+                               {
+                                       ClassNotFoundException wrapperCnf = new 
ClassNotFoundException();
+                                       wrapperCnf.initCause(ex);
+                                       throw wrapperCnf;
+                               }
                        }
                        return candidate;
                }
+
+               /*
+                * This method is an a copy of the super-method, with 
Class.forName replaced with a call to
+                * resolveClassByName.
+                */
+               @Override
+               protected Class<?> resolveProxyClass(String[] interfaces)
+                       throws ClassNotFoundException, IOException
+               {
+                       try
+                       {
+                               return super.resolveProxyClass(interfaces);
+                       }
+                       catch (ClassNotFoundException cnfEx)
+                       {
+                               // ignore this exception.
+                               log.debug(
+                                       "Proxy Class not found by the object 
outputstream itself, trying the IClassResolver");
+
+                               ClassLoader latestLoader = 
latestUserDefinedLoader();
+                               ClassLoader nonPublicLoader = null;
+                               boolean hasNonPublicInterface = false;
+
+                               // define proxy in class loader of non-public 
interface(s), if any
+                               Class<?>[] classObjs = new 
Class<?>[interfaces.length];
+                               for (int i = 0; i < interfaces.length; i++)
+                               {
+                                       Class<?> cl = 
resolveClassByName(interfaces[i], latestLoader);
+                                       if ((cl.getModifiers() & 
Modifier.PUBLIC) == 0)
+                                       {
+                                               if (hasNonPublicInterface)
+                                               {
+                                                       if (nonPublicLoader != 
cl.getClassLoader())
+                                                       {
+                                                               throw new 
IllegalAccessError(
+                                                                       
"conflicting non-public interface class loaders");
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       nonPublicLoader = 
cl.getClassLoader();
+                                                       hasNonPublicInterface = 
true;
+                                               }
+                                       }
+                                       classObjs[i] = cl;
+                               }
+                               try
+                               {
+                                       return Proxy.getProxyClass(
+                                               hasNonPublicInterface ? 
nonPublicLoader : latestLoader, classObjs);
+                               }
+                               catch (IllegalArgumentException e)
+                               {
+                                       throw new ClassNotFoundException(null, 
e);
+                               }
+                       }
+               }
+
+               /*
+                * Method in the superclass is private, call it via reflection.
+                */
+               private static ClassLoader latestUserDefinedLoader()
+               {
+                       try
+                       {
+                               Method originalMethod =
+                                       
ObjectInputStream.class.getDeclaredMethod("latestUserDefinedLoader");
+                               originalMethod.setAccessible(true);
+                               return (ClassLoader) 
originalMethod.invoke(null);
+                       }
+                       catch (IllegalAccessException | 
IllegalArgumentException | InvocationTargetException
+                                       | NoSuchMethodException | 
SecurityException e)
+                       {
+                               // should not happen
+                               throw new WicketRuntimeException(e);
+                       }
+               }
        }
+
        /**
         * Write objects to the wrapped output stream and log a meaningful 
message for serialization
         * problems.

Reply via email to