Author: bayard
Date: Tue Aug 2 06:57:04 2011
New Revision: 1153046
URL: http://svn.apache.org/viewvc?rev=1153046&view=rev
Log:
Applying Sven Ludwig's patch from LANG-626. This modifies the
SerializationUtils.clone method to use the threadContextLoader if it is unable
to find a class using the object's current classloader. This should (hopefully)
help with Weblogic and Tomcat situations where Lang is outside the web-inf for
some reason (likely user error with Tomcat, by design for Weblogic)
Modified:
commons/proper/lang/trunk/pom.xml
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/SerializationUtils.java
Modified: commons/proper/lang/trunk/pom.xml
URL:
http://svn.apache.org/viewvc/commons/proper/lang/trunk/pom.xml?rev=1153046&r1=1153045&r2=1153046&view=diff
==============================================================================
--- commons/proper/lang/trunk/pom.xml (original)
+++ commons/proper/lang/trunk/pom.xml Tue Aug 2 06:57:04 2011
@@ -249,6 +249,9 @@
<name>Chris Feldhacker</name>
</contributor>
<contributor>
+ <name>Roland Foerther</name>
+ </contributor>
+ <contributor>
<name>Pete Gieser</name>
</contributor>
<contributor>
@@ -291,6 +294,9 @@
<name>Eli Lindsey</name>
</contributor>
<contributor>
+ <name>Sven Ludwig</name>
+ </contributor>
+ <contributor>
<name>Craig R. McClanahan</name>
</contributor>
<contributor>
Modified:
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/SerializationUtils.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/SerializationUtils.java?rev=1153046&r1=1153045&r2=1153046&view=diff
==============================================================================
---
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/SerializationUtils.java
(original)
+++
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/SerializationUtils.java
Tue Aug 2 06:57:04 2011
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.io.Serializable;
@@ -73,14 +74,36 @@ public class SerializationUtils {
* @throws SerializationException (runtime) if the serialization fails
*/
public static <T extends Serializable> T clone(T object) {
- /*
- * when we serialize and deserialize an object,
- * it is reasonable to assume the deserialized object
- * is of the same type as the original serialized object
- */
- @SuppressWarnings("unchecked")
- final T result = (T) deserialize(serialize(object));
- return result;
+ if (object == null) {
+ return null;
+ }
+ byte[] objectData = serialize(object);
+ ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
+
+ ClassLoaderAwareObjectInputStream in = null;
+ try {
+ // stream closed in the finally
+ in = new ClassLoaderAwareObjectInputStream(bais,
object.getClass().getClassLoader());
+ /*
+ * when we serialize and deserialize an object,
+ * it is reasonable to assume the deserialized object
+ * is of the same type as the original serialized object
+ */
+ return (T) in.readObject();
+
+ } catch (ClassNotFoundException ex) {
+ throw new SerializationException("ClassNotFoundException while
reading cloned object data", ex);
+ } catch (IOException ex) {
+ throw new SerializationException("IOException while reading cloned
object data", ex);
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException ex) {
+ throw new SerializationException("IOException on closing
cloned object data InputStream.", ex);
+ }
+ }
}
// Serialize
@@ -195,4 +218,52 @@ public class SerializationUtils {
return deserialize(bais);
}
+ /**
+ * <p>Custom specialization of the standard JDK {@link
java.io.ObjectInputStream}
+ * that uses a custom <code>ClassLoader</code> to resolve a class.
+ * If the specified <code>ClassLoader</code> is not able to resolve the
class,
+ * the context classloader of the current thread will be used.
+ * This way, the standard deserialization work also in web-application
+ * containers and application servers, no matter in which of the
+ * <code>ClassLoader</code> the particular class that encapsulates
+ * serialization/deserialization lives. </p>
+ *
+ * <p>For more in-depth information about the problem for which this
+ * class here is a workaround, see the JIRA issue LANG-626. </p>
+ */
+ static class ClassLoaderAwareObjectInputStream extends ObjectInputStream {
+ private ClassLoader classLoader;
+
+ /**
+ * Constructor.
+ * @param in The <code>InputStream</code>.
+ * @param classLoader classloader to use
+ * @throws IOException if an I/O error occurs while reading stream
header.
+ * @see java.io.ObjectInputStream
+ */
+ public ClassLoaderAwareObjectInputStream(InputStream in, ClassLoader
classLoader) throws IOException {
+ super(in);
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Overriden version that uses the parametrized
<code>ClassLoader</code> or the <code>ClassLoader</code>
+ * of the current <code>Thread</code> to resolve the class.
+ * @param desc An instance of class <code>ObjectStreamClass</code>.
+ * @return A <code>Class</code> object corresponding to
<code>desc</code>.
+ * @throws IOException Any of the usual Input/Output exceptions.
+ * @throws ClassNotFoundException If class of a serialized object
cannot be found.
+ */
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws
IOException, ClassNotFoundException {
+ String name = desc.getName();
+ try {
+ return Class.forName(name, false, classLoader);
+ } catch (ClassNotFoundException ex) {
+ return Class.forName(name, false,
Thread.currentThread().getContextClassLoader());
+ }
+ }
+
+ }
+
}