diff options
Diffstat (limited to 'java/client')
| -rw-r--r-- | java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java | 3 | ||||
| -rw-r--r-- | java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java | 136 |
2 files changed, 138 insertions, 1 deletions
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java index 637d9dd692..370e2d6c55 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java @@ -33,6 +33,7 @@ import javax.jms.ObjectMessage; import org.apache.mina.common.ByteBuffer; import org.apache.qpid.AMQException; +import org.apache.qpid.client.util.ClassLoadingAwareObjectInputStream; public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessage { @@ -136,7 +137,7 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag try { _data.rewind(); - in = new ObjectInputStream(_data.asInputStream()); + in = new ClassLoadingAwareObjectInputStream(_data.asInputStream()); return (Serializable) in.readObject(); } diff --git a/java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java b/java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java new file mode 100644 index 0000000000..e89f0c5643 --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java @@ -0,0 +1,136 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.client.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; +import java.lang.reflect.Proxy; +import java.util.HashMap; + + +/** + * <code>ClassLoadingAwareObjectInputStream</code> is an Extention of Object input stream to be used + * to de-serialize JMS Object Messages. + * + * <p>This was introduced to resolve the class loading issues which can happen when we use the client + * libraries in a complex class loading Environment.</p> + */ +public class ClassLoadingAwareObjectInputStream extends ObjectInputStream +{ + /** <p>Class loader instance which loaded this class. + * It will be used to load classes when we failed to load classes from dynamic class loading</p> */ + private static final ClassLoader _ON_FAULT_CLASS_LOADER = + ClassLoadingAwareObjectInputStream.class.getClassLoader(); + + /** <p>Maps primitive type names to corresponding class objects.</p> */ + private static final HashMap<String, Class> _primitives = new HashMap<String, Class>(8, 1.0F); + + + public ClassLoadingAwareObjectInputStream(InputStream in) throws IOException + { + super(in); + } + + @Override + protected Class resolveClass(ObjectStreamClass classDesc) + throws IOException, ClassNotFoundException + { + + // Here we use TTCL as our primary class loader to load the classes + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + + return load(classDesc.getName(), cl); + } + + + @Override + protected Class resolveProxyClass(String[] interfaces) + throws IOException, ClassNotFoundException + { + // Here we use TTCL as our primary class loader to load the classes + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + + Class[] cinterfaces = new Class[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) + { + cinterfaces[i] = load(interfaces[i], cl); + } + + try + { + return Proxy.getProxyClass(cinterfaces[0].getClassLoader(), cinterfaces); + } + catch (IllegalArgumentException e) + { + throw new ClassNotFoundException(null, e); + } + } + + /** + * <p> + * Method we used to load class that are needed to de-serialize the objects. </p> + * <p> + * Here we first look up for the objects from the given class loader and if its not there + * we will be using the class loader of this class. + * </p> + * @param className Class name to lookup + * @param cl primary class loader which we 1st use to lookup + * @return Class instance we are looking for + * @throws ClassNotFoundException if both primary and secondary lockup's failed. + */ + private Class load(String className, ClassLoader cl) + throws ClassNotFoundException + { + try + { + return Class.forName(className, false, cl); + } + catch (ClassNotFoundException e) + { + final Class clazz = _primitives.get(className); + + if (clazz != null) + { + return clazz; + } else + { + return Class.forName(className, false, _ON_FAULT_CLASS_LOADER); + } + } + } + + + + static { + _primitives.put("boolean", boolean.class); + _primitives.put("byte", byte.class); + _primitives.put("char", char.class); + _primitives.put("short", short.class); + _primitives.put("int", int.class); + _primitives.put("long", long.class); + _primitives.put("float", float.class); + _primitives.put("double", double.class); + _primitives.put("void", void.class); + } + +} |
