diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/CachingClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/CachingClassResolver.java new file mode 100644 index 0000000000..93524d5438 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/CachingClassResolver.java @@ -0,0 +1,31 @@ +package org.jboss.netty.handler.codec.serialization; + +import java.util.Map; + +class CachingClassResolver implements ClassResolver { + + private final Map> classCache; + private final ClassResolver delegate; + + CachingClassResolver(ClassResolver delegate, Map> classCache) { + this.delegate = delegate; + this.classCache = classCache; + } + + @Override + public Class resolve(String className) throws ClassNotFoundException { + // Query the cache first. + Class clazz; + clazz = classCache.get(className); + if (clazz != null) { + return clazz; + } + + // And then try to load. + clazz = delegate.resolve(className); + + classCache.put(className, clazz); + return clazz; + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java new file mode 100644 index 0000000000..a6fa1c52d7 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java @@ -0,0 +1,7 @@ +package org.jboss.netty.handler.codec.serialization; + +interface ClassResolver { + + Class resolve(String className) throws ClassNotFoundException; + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java new file mode 100644 index 0000000000..e802838080 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java @@ -0,0 +1,24 @@ +package org.jboss.netty.handler.codec.serialization; + +import java.util.HashMap; + +public class ClassResolvers { + + public static ClassResolver cachingResolver(ClassLoader classLoader) { + if (classLoader == null) { + classLoader = defaultClassLoader(); + } + + return new CachingClassResolver(new ClassloaderClassResolver(classLoader), new HashMap>()); + } + + static ClassLoader defaultClassLoader() { + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + if (contextClassLoader != null) { + return contextClassLoader; + } + + return CompactObjectInputStream.class.getClassLoader(); + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java new file mode 100644 index 0000000000..545e8e3f08 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java @@ -0,0 +1,16 @@ +package org.jboss.netty.handler.codec.serialization; + +class ClassloaderClassResolver implements ClassResolver { + + private final ClassLoader classLoader; + + ClassloaderClassResolver(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public Class resolve(String className) throws ClassNotFoundException { + return classLoader.loadClass(className); + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java index 95c9eccec0..2ced2188d4 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java @@ -21,8 +21,6 @@ import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.io.StreamCorruptedException; -import java.util.HashMap; -import java.util.Map; /** * @author The Netty Project @@ -32,21 +30,12 @@ import java.util.Map; * */ class CompactObjectInputStream extends ObjectInputStream { + + private final ClassResolver classResolver; - private final Map> classCache = new HashMap>(); - private final ClassLoader classLoader; - - CompactObjectInputStream(InputStream in) throws IOException { - this(in, null); - } - - CompactObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException { + CompactObjectInputStream(InputStream in, ClassResolver classResolver) throws IOException { super(in); - if (classLoader == null) { - this.classLoader = defaultClassLoader(); - } else { - this.classLoader = classLoader; - } + this.classResolver = classResolver; } @Override @@ -70,7 +59,7 @@ class CompactObjectInputStream extends ObjectInputStream { return super.readClassDescriptor(); case CompactObjectOutputStream.TYPE_THIN_DESCRIPTOR: String className = readUTF(); - Class clazz = loadClass(className); + Class clazz = classResolver.resolve(className); return ObjectStreamClass.lookupAny(clazz); default: throw new StreamCorruptedException( @@ -82,7 +71,7 @@ class CompactObjectInputStream extends ObjectInputStream { protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { Class clazz; try { - clazz = loadClass(desc.getName()); + clazz = classResolver.resolve(desc.getName()); } catch (ClassNotFoundException ex) { clazz = super.resolveClass(desc); } @@ -90,28 +79,4 @@ class CompactObjectInputStream extends ObjectInputStream { return clazz; } - protected Class loadClass(String className) throws ClassNotFoundException { - // Query the cache first. - Class clazz; - clazz = classCache.get(className); - if (clazz != null) { - return clazz; - } - - // And then try to load. - clazz = classLoader.loadClass(className); - - classCache.put(className, clazz); - return clazz; - } - - private static ClassLoader defaultClassLoader() { - final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - if (contextClassLoader != null) { - return contextClassLoader; - } - - return CompactObjectInputStream.class.getClassLoader(); - } - } diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java index 3bf80a82ca..4efab6c9c8 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java @@ -43,7 +43,7 @@ import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; */ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { - private final ClassLoader classLoader; + private final ClassResolver classResolver; /** * Creates a new decoder whose maximum object size is {@code 1048576} @@ -64,7 +64,7 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { * will be raised. */ public ObjectDecoder(int maxObjectSize) { - this(maxObjectSize, null); + this(maxObjectSize, ClassResolvers.cachingResolver(null)); } /** @@ -74,12 +74,12 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { * if the length of the received object is greater * than this value, {@link StreamCorruptedException} * will be raised. - * @param classLoader the {@link ClassLoader} which will load the class + * @param classResolver the {@link ClassResolver} which will load the class * of the serialized object */ - public ObjectDecoder(int maxObjectSize, ClassLoader classLoader) { + public ObjectDecoder(int maxObjectSize, ClassResolver classResolver) { super(maxObjectSize, 0, 4, 0, 4); - this.classLoader = classLoader; + this.classResolver = classResolver; } @Override @@ -92,7 +92,7 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { } return new CompactObjectInputStream( - new ChannelBufferInputStream(frame), classLoader).readObject(); + new ChannelBufferInputStream(frame), classResolver).readObject(); } @Override diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java index aa4aa439c0..158f0ad3a1 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java @@ -119,7 +119,7 @@ public class ObjectDecoderInputStream extends InputStream implements "data length too big: " + dataLen + " (max: " + maxObjectSize + ')'); } - return new CompactObjectInputStream(in, classLoader).readObject(); + return new CompactObjectInputStream(in, ClassResolvers.cachingResolver(classLoader)).readObject(); } @Override