AMQ-4746: Fixed ClassLoadingAwareObjectInputStream to load simple types first, using same logic as in Camel. This helps with AMQ clients in other runtimes such as Applet based or whatnot.

This commit is contained in:
Claus Ibsen 2013-11-02 15:24:01 +01:00
parent 20747eedca
commit 6e49ef3a60
1 changed files with 75 additions and 25 deletions

View File

@ -21,19 +21,16 @@ import java.io.InputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectStreamClass; import java.io.ObjectStreamClass;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.HashMap;
@SuppressWarnings("rawtypes") import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClassLoadingAwareObjectInputStream extends ObjectInputStream { public class ClassLoadingAwareObjectInputStream extends ObjectInputStream {
private static final Logger LOG = LoggerFactory.getLogger(ClassLoadingAwareObjectInputStream.class);
private static final ClassLoader FALLBACK_CLASS_LOADER = private static final ClassLoader FALLBACK_CLASS_LOADER =
ClassLoadingAwareObjectInputStream.class.getClassLoader(); ClassLoadingAwareObjectInputStream.class.getClassLoader();
/**
* Maps primitive type names to corresponding class objects.
*/
private static final HashMap<String, Class> primClasses = new HashMap<String, Class>(8, 1.0F);
private final ClassLoader inLoader; private final ClassLoader inLoader;
public ClassLoadingAwareObjectInputStream(InputStream in) throws IOException { public ClassLoadingAwareObjectInputStream(InputStream in) throws IOException {
@ -72,31 +69,84 @@ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream {
} }
private Class<?> load(String className, ClassLoader... cl) throws ClassNotFoundException { private Class<?> load(String className, ClassLoader... cl) throws ClassNotFoundException {
// check for simple types first
final Class<?> clazz = loadSimpleType(className);
if (clazz != null) {
LOG.trace("Loaded class: {} as simple type -> ", className, clazz);
return clazz;
}
// try the different class loaders
for (ClassLoader loader : cl) { for (ClassLoader loader : cl) {
LOG.trace("Attempting to load class: {} using classloader: {}", className, cl);
try { try {
return Class.forName(className, false, loader); Class<?> answer = Class.forName(className, false, loader);
if (LOG.isTraceEnabled()) {
LOG.trace("Loaded class: {} using classloader: {} -> ", new Object[]{className, cl, answer});
}
return answer;
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
LOG.trace("Class not found: {} using classloader: {}", className, cl);
// ignore // ignore
} }
} }
// fallback
final Class<?> clazz = (Class<?>) primClasses.get(className); // and then the fallback class loader
if (clazz != null) { return Class.forName(className, false, FALLBACK_CLASS_LOADER);
return clazz;
} else {
return Class.forName(className, false, FALLBACK_CLASS_LOADER);
}
} }
static { /**
primClasses.put("boolean", boolean.class); * Load a simple type
primClasses.put("byte", byte.class); *
primClasses.put("char", char.class); * @param name the name of the class to load
primClasses.put("short", short.class); * @return the class or <tt>null</tt> if it could not be loaded
primClasses.put("int", int.class); */
primClasses.put("long", long.class); public static Class<?> loadSimpleType(String name) {
primClasses.put("float", float.class); // code from ObjectHelper.loadSimpleType in Apache Camel
primClasses.put("double", double.class);
primClasses.put("void", void.class); // special for byte[] or Object[] as its common to use
if ("java.lang.byte[]".equals(name) || "byte[]".equals(name)) {
return byte[].class;
} else if ("java.lang.Byte[]".equals(name) || "Byte[]".equals(name)) {
return Byte[].class;
} else if ("java.lang.Object[]".equals(name) || "Object[]".equals(name)) {
return Object[].class;
} else if ("java.lang.String[]".equals(name) || "String[]".equals(name)) {
return String[].class;
// and these is common as well
} else if ("java.lang.String".equals(name) || "String".equals(name)) {
return String.class;
} else if ("java.lang.Boolean".equals(name) || "Boolean".equals(name)) {
return Boolean.class;
} else if ("boolean".equals(name)) {
return boolean.class;
} else if ("java.lang.Integer".equals(name) || "Integer".equals(name)) {
return Integer.class;
} else if ("int".equals(name)) {
return int.class;
} else if ("java.lang.Long".equals(name) || "Long".equals(name)) {
return Long.class;
} else if ("long".equals(name)) {
return long.class;
} else if ("java.lang.Short".equals(name) || "Short".equals(name)) {
return Short.class;
} else if ("short".equals(name)) {
return short.class;
} else if ("java.lang.Byte".equals(name) || "Byte".equals(name)) {
return Byte.class;
} else if ("byte".equals(name)) {
return byte.class;
} else if ("java.lang.Float".equals(name) || "Float".equals(name)) {
return Float.class;
} else if ("float".equals(name)) {
return float.class;
} else if ("java.lang.Double".equals(name) || "Double".equals(name)) {
return Double.class;
} else if ("double".equals(name)) {
return double.class;
}
return null;
} }
} }