Repository: wicket
Updated Branches:
  refs/heads/classloadingfix [created] 5b7ff7d03


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/5b7ff7d0
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/5b7ff7d0
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/5b7ff7d0

Branch: refs/heads/classloadingfix
Commit: 5b7ff7d03a9a4fe1ec20a7021ab7ec46ef2fbca8
Parents: 137fa9e
Author: Emond Papegaaij <[email protected]>
Authored: Wed Apr 5 14:54:28 2017 +0200
Committer: Emond Papegaaij <[email protected]>
Committed: Wed Apr 5 14:54:28 2017 +0200

----------------------------------------------------------------------
 .../wicket/serialize/java/JavaSerializer.java   | 111 ++++++++++++++++---
 1 file changed, 98 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/5b7ff7d0/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..39c09ce 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,45 +192,126 @@ 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;
                        }
+               }
 
+               private Class< ? > resolveClassByName(String className) throws 
ClassNotFoundException
+               {
+                       try
+                       {
+                               return Class.forName(className, false, 
latestUserDefinedLoader());
+                       }
+                       catch (ClassNotFoundException cnfEx)
+                       {
+                               Class< ? > ret = 
resolveClassInWicket(className);
+                               if (ret == null)
+                                       throw cnfEx;
+                               return ret;
+                       }
+               }
 
-                       Class<?> candidate = null;
+               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)
                        {
                                if (ex.getCause() instanceof 
ClassNotFoundException)
                                {
-                                       throw 
(ClassNotFoundException)ex.getCause();
+                                       throw (ClassNotFoundException) 
ex.getCause();
+                               }
+                               else
+                               {
+                                       ClassNotFoundException wrapperCnf = new 
ClassNotFoundException();
+                                       wrapperCnf.initCause(ex);
+                                       throw wrapperCnf;
                                }
                        }
                        return candidate;
                }
+
+               @Override
+               protected Class< ? > resolveProxyClass(String[] interfaces) 
throws ClassNotFoundException
+               {
+                       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]);
+                               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);
+                       }
+               }
+
+               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