Fix for bug
authorfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Sat, 5 Apr 2008 22:03:59 +0000 (22:03 +0000)
committerfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Sat, 5 Apr 2008 22:03:59 +0000 (22:03 +0000)
https://issues.apache.org/bugzilla/show_bug.cgi
The ObjectInputStream.resolveProxyClass uses some funky native code base to retrieve what class loader to use, and it doesn't return the correct one. So we have to mimic the behavior in that class but use our class loaders instead

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@645184 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/tribes/io/ReplicationStream.java

index 38cd29b..ff3bea8 100644 (file)
@@ -22,6 +22,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectStreamClass;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 
 /**
  * Custom subclass of <code>ObjectInputStream</code> that loads from the
@@ -42,7 +44,6 @@ public final class ReplicationStream extends ObjectInputStream {
      */
     private ClassLoader[] classLoaders = null;
     
-
     /**
      * Construct a new instance of CustomObjectInputStream
      *
@@ -71,23 +72,69 @@ public final class ReplicationStream extends ObjectInputStream {
     public Class resolveClass(ObjectStreamClass classDesc)
         throws ClassNotFoundException, IOException {
         String name = classDesc.getName();
-        boolean tryRepFirst = name.startsWith("org.apache.catalina.tribes");
         try {
-            try
-            {
-                if ( tryRepFirst ) return findReplicationClass(name);
-                else return findExternalClass(name);
-            }
-            catch ( Exception x )
-            {
-                if ( tryRepFirst ) return findExternalClass(name);
-                else return findReplicationClass(name);
-            }
+            return resolveClass(name);
         } catch (ClassNotFoundException e) {
             return super.resolveClass(classDesc);
         }
     }
     
+    public Class resolveClass(String name)
+        throws ClassNotFoundException, IOException {
+
+        boolean tryRepFirst = name.startsWith("org.apache.catalina.tribes");
+            try {
+            if (tryRepFirst)
+                return findReplicationClass(name);
+            else
+                return findExternalClass(name);
+        } catch (Exception x) {
+            if (tryRepFirst)
+                return findExternalClass(name);
+            else
+                return findReplicationClass(name);
+        }
+    }
+    
+    /**
+     * ObjectInputStream.resolveProxyClass has some funky way of using 
+     * the incorrect class loader to resolve proxy classes, let's do it our way instead
+     */
+    @Override
+    protected Class<?> resolveProxyClass(String[] interfaces)
+            throws IOException, ClassNotFoundException {
+        
+        ClassLoader latestLoader = (classLoaders!=null && classLoaders.length==0)?null:classLoaders[0];
+        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 = this.resolveClass(interfaces[i]);
+            if (latestLoader==null) latestLoader = cl.getClassLoader();
+            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);
+        }
+    }
+
+    
     public Class findReplicationClass(String name)
         throws ClassNotFoundException, IOException {
         Class clazz = Class.forName(name, false, getClass().getClassLoader());