--- container/modules/cluster/src/share/org/apache/catalina/cluster/session/ReplicationStream.java (revision 1156533)
+++ container/modules/cluster/src/share/org/apache/catalina/cluster/session/ReplicationStream.java (working copy)
@@ -22,6 +22,8 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
/**
* Custom subclass of ObjectInputStream
that loads from the
@@ -86,6 +88,43 @@
}
}
+ /**
+ * ObjectInputStream.resolveProxyClass has some funky way of using
+ * the incorrect class loader to resolve proxy classes, let's do it our way instead
+ */
+ protected Class resolveProxyClass(String[] interfaces)
+ throws IOException, ClassNotFoundException {
+
+ ClassLoader latestLoader = classLoader;
+ 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.findWebappClass(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 {
return Class.forName(name, false, getClass().getClassLoader());
--- container/modules/groupcom/src/share/org/apache/catalina/tribes/io/ReplicationStream.java (revision 1156533)
+++ container/modules/groupcom/src/share/org/apache/catalina/tribes/io/ReplicationStream.java (working copy)
@@ -22,6 +22,8 @@
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 ObjectInputStream
that loads from the
@@ -71,23 +73,68 @@
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
+ */
+ 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());