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());
+            }
+        }
+
+    }
+
 }


Reply via email to