Author: pedro
Date: Thu Jun  9 15:50:28 2011
New Revision: 1133952

URL: http://svn.apache.org/viewvc?rev=1133952&view=rev
Log:
removing IObjectStreamFactory & Co and moving the default (de)serialization 
code to JavaSerializer
Issue: WICKET-3778

Removed:
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/io/ClassStreamHandler.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/io/IObjectStreamFactory.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/io/WicketObjectInputStream.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/io/WicketObjectOutputStream.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/io/WicketObjectStreamFactory.java
    
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/util/io/WicketOutputStreamTest.java
Modified:
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/lang/WicketObjects.java
    
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java?rev=1133952&r1=1133951&r2=1133952&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
 Thu Jun  9 15:50:28 2011
@@ -16,19 +16,39 @@
  */
 package org.apache.wicket.serialize.java;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.ThreadContext;
+import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.application.IClassResolver;
 import org.apache.wicket.serialize.ISerializer;
-import org.apache.wicket.util.io.IObjectStreamFactory;
-import org.apache.wicket.util.lang.WicketObjects;
+import org.apache.wicket.settings.IApplicationSettings;
+import org.apache.wicket.util.io.IOUtils;
+import org.apache.wicket.util.io.SerializableChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * An implementation of {@link ISerializer} based on Java Serialization 
(ObjectOutputStream,
  * ObjectInputStream)
  * 
+ * Requires the application key to enable serialization and deserialisation 
outside thread in which
+ * application thread local is set
+ * 
  * @see IObjectStreamFactory
  */
 public class JavaSerializer implements ISerializer
 {
+       private static final Logger log = 
LoggerFactory.getLogger(JavaSerializer.class);
        /**
         * The key of the application which can be used later to find the 
proper {@link IClassResolver}
         */
@@ -44,14 +64,189 @@ public class JavaSerializer implements I
                this.applicationKey = applicationKey;
        }
 
-       public byte[] serialize(final Object page)
+       public byte[] serialize(final Object object)
        {
-               return WicketObjects.objectToByteArray(page, applicationKey);
+               try
+               {
+                       final ByteArrayOutputStream out = new 
ByteArrayOutputStream();
+                       ObjectOutputStream oos = null;
+                       try
+                       {
+                               oos = new CheckerObjectOutputStream(out);
+                               oos.writeObject(applicationKey);
+                               oos.writeObject(object);
+                       }
+                       finally
+                       {
+                               try
+                               {
+                                       IOUtils.close(oos);
+                               }
+                               finally
+                               {
+                                       out.close();
+                               }
+                       }
+                       return out.toByteArray();
+               }
+               catch (Exception e)
+               {
+                       log.error("Error serializing object " + 
object.getClass() + " [object=" + object + "]",
+                               e);
+               }
+               return null;
        }
 
        public Object deserialize(final byte[] data)
        {
-               return WicketObjects.byteArrayToObject(data);
+               ThreadContext old = ThreadContext.get(false);
+               try
+               {
+                       final ByteArrayInputStream in = new 
ByteArrayInputStream(data);
+                       ObjectInputStream ois = null;
+                       try
+                       {
+                               ois = new ClassResolverObjectInputStream(in);
+                               String applicationName = 
(String)ois.readObject();
+                               if (applicationName != null && 
!Application.exists())
+                               {
+                                       Application app = 
Application.get(applicationName);
+                                       if (app != null)
+                                       {
+                                               
ThreadContext.setApplication(app);
+                                       }
+                               }
+                               return ois.readObject();
+                       }
+                       finally
+                       {
+                               try
+                               {
+                                       IOUtils.close(ois);
+                               }
+                               finally
+                               {
+                                       in.close();
+                               }
+                       }
+               }
+               catch (ClassNotFoundException e)
+               {
+                       throw new RuntimeException("Could not deserialize 
object using JavaSerializer", e);
+               }
+               catch (IOException e)
+               {
+                       throw new RuntimeException("Could not deserialize 
object using JavaSerializer", e);
+               }
+               finally
+               {
+                       ThreadContext.restore(old);
+               }
        }
 
+       /**
+        * Extend {@link ObjectInputStream} to add framework class resolution 
logic.
+        */
+       private static class ClassResolverObjectInputStream extends 
ObjectInputStream
+       {
+               public ClassResolverObjectInputStream(InputStream in) throws 
IOException
+               {
+                       super(in);
+               }
+
+               // This override is required to resolve classes inside in 
different bundle, i.e.
+               // The classes can be resolved by OSGI classresolver 
implementation
+               @Override
+               protected Class<?> resolveClass(ObjectStreamClass desc) throws 
IOException,
+                       ClassNotFoundException
+               {
+                       String className = desc.getName();
+
+                       try
+                       {
+                               return super.resolveClass(desc);
+                       }
+                       catch (ClassNotFoundException ex1)
+                       {
+                               // ignore this exception.
+                               log.debug("Class not found by the object 
outputstream itself, trying the IClassResolver");
+                       }
+
+
+                       Class<?> candidate = null;
+                       try
+                       {
+                               // Can the application always be taken??
+                               // Should be if serialization happened in 
thread with application set
+                               // (WICKET-2195)
+                               Application application = Application.get();
+                               IApplicationSettings applicationSettings = 
application.getApplicationSettings();
+                               IClassResolver classResolver = 
applicationSettings.getClassResolver();
+
+                               candidate = 
classResolver.resolveClass(className);
+                               if (candidate == null)
+                               {
+                                       candidate = super.resolveClass(desc);
+                               }
+                       }
+                       catch (WicketRuntimeException ex)
+                       {
+                               if (ex.getCause() instanceof 
ClassNotFoundException)
+                               {
+                                       throw 
(ClassNotFoundException)ex.getCause();
+                               }
+                       }
+                       return candidate;
+               }
+       }
+       /**
+        * Write objects to the wrapped output stream and log a meaningful 
message for serialization
+        * problems
+        */
+       private static class CheckerObjectOutputStream extends 
ObjectOutputStream
+       {
+               public CheckerObjectOutputStream(OutputStream out) throws 
IOException
+               {
+                       super(out);
+               }
+
+               @Override
+               protected final void writeObjectOverride(final Object obj) 
throws IOException
+               {
+                       try
+                       {
+                               super.writeObject(obj);
+                       }
+                       catch (IOException e)
+                       {
+                               if (SerializableChecker.isAvailable())
+                               {
+                                       // trigger serialization again, but 
this time gather
+                                       // some more info
+                                       new 
SerializableChecker((NotSerializableException)e).writeObject(obj);
+                                       // if we get here, we didn't fail, 
while we
+                                       // should;
+                                       throw e;
+                               }
+                               throw e;
+                       }
+                       catch (RuntimeException e)
+                       {
+                               log.error("error writing object " + obj + ": " 
+ e.getMessage(), e);
+                               throw e;
+                       }
+               }
+
+               @Override
+               public void flush() throws IOException
+               {
+                       super.flush();
+               }
+
+               @Override
+               public void close() throws IOException
+               {
+                       super.close();
+               }
+       }
 }

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/lang/WicketObjects.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/lang/WicketObjects.java?rev=1133952&r1=1133951&r2=1133952&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/lang/WicketObjects.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/lang/WicketObjects.java
 Thu Jun  9 15:50:28 2011
@@ -29,14 +29,10 @@ import java.util.HashMap;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.Component;
-import org.apache.wicket.ThreadContext;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.application.IClassResolver;
 import org.apache.wicket.settings.IApplicationSettings;
 import org.apache.wicket.util.io.ByteCountingOutputStream;
-import org.apache.wicket.util.io.IOUtils;
-import org.apache.wicket.util.io.IObjectStreamFactory;
-import 
org.apache.wicket.util.io.IObjectStreamFactory.DefaultObjectStreamFactory;
 import org.apache.wicket.util.string.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -237,62 +233,6 @@ public class WicketObjects
        }
 
        /**
-        * De-serializes an object from a byte array.
-        * 
-        * @param data
-        *            The serialized object
-        * @return The object
-        */
-       public static Object byteArrayToObject(final byte[] data)
-       {
-               ThreadContext old = ThreadContext.get(false);
-               try
-               {
-                       final ByteArrayInputStream in = new 
ByteArrayInputStream(data);
-                       ObjectInputStream ois = null;
-                       try
-                       {
-                               ois = 
objectStreamFactory.newObjectInputStream(in);
-                               String applicationName = 
(String)ois.readObject();
-                               if (applicationName != null && 
!Application.exists())
-                               {
-                                       Application app = 
Application.get(applicationName);
-                                       if (app != null)
-                                       {
-                                               
ThreadContext.setApplication(app);
-                                       }
-                               }
-                               return ois.readObject();
-                       }
-                       finally
-                       {
-                               try
-                               {
-                                       IOUtils.close(ois);
-                               }
-                               finally
-                               {
-                                       in.close();
-                               }
-                       }
-               }
-               catch (ClassNotFoundException e)
-               {
-                       throw new RuntimeException("Could not deserialize 
object using `" +
-                               objectStreamFactory.getClass().getName() + "` 
object factory", e);
-               }
-               catch (IOException e)
-               {
-                       throw new RuntimeException("Could not deserialize 
object using `" +
-                               objectStreamFactory.getClass().getName() + "` 
object factory", e);
-               }
-               finally
-               {
-                       ThreadContext.restore(old);
-               }
-       }
-
-       /**
         * Makes a deep clone of an object by serializing and deserializing it. 
The object must be fully
         * serializable to be cloned. This method will not clone wicket 
Components, it will just reuse
         * those instances so that the complete component tree is not copied 
over only the model data.
@@ -331,13 +271,6 @@ public class WicketObjects
        }
 
        /**
-        * The default object stream factory to use. Keep this as a static here 
opposed to in
-        * Application, as the Application most likely isn't available in the 
threads we'll be using
-        * this with.
-        */
-       private static IObjectStreamFactory objectStreamFactory = new 
IObjectStreamFactory.DefaultObjectStreamFactory();
-
-       /**
         * Strategy for calculating sizes of objects. Note: I didn't make this 
an application setting as
         * we have enough of those already, and the typical way this probably 
would be used is that
         * install a different one according to the JDK version used, so 
varying them between
@@ -452,98 +385,6 @@ public class WicketObjects
        }
 
        /**
-        * Serializes an object into a byte array.
-        * 
-        * @param object
-        *            The object
-        * 
-        * @param applicationName
-        *            The name of application - required when serialization and 
deserialisation happen
-        *            outside thread in which application thread local is set
-        * 
-        * @return The serialized object
-        */
-       public static byte[] objectToByteArray(final Object object, String 
applicationName)
-       {
-               try
-               {
-                       final ByteArrayOutputStream out = new 
ByteArrayOutputStream();
-                       ObjectOutputStream oos = null;
-                       try
-                       {
-                               oos = 
objectStreamFactory.newObjectOutputStream(out);
-                               oos.writeObject(applicationName);
-                               oos.writeObject(object);
-                       }
-                       finally
-                       {
-                               try
-                               {
-                                       IOUtils.close(oos);
-                               }
-                               finally
-                               {
-                                       out.close();
-                               }
-                       }
-                       return out.toByteArray();
-               }
-               catch (Exception e)
-               {
-                       log.error("Error serializing object " + 
object.getClass() + " [object=" + object + "]",
-                               e);
-               }
-               return null;
-       }
-
-       /**
-        * Serializes an object into a byte array.
-        * 
-        * @param object
-        *            The object
-        * @return The serialized object
-        */
-       public static byte[] objectToByteArray(final Object object)
-       {
-               try
-               {
-                       final ByteArrayOutputStream out = new 
ByteArrayOutputStream();
-                       ObjectOutputStream oos = null;
-                       try
-                       {
-                               oos = 
objectStreamFactory.newObjectOutputStream(out);
-                               if (Application.exists())
-                               {
-                                       
oos.writeObject(Application.get().getApplicationKey());
-                               }
-                               else
-                               {
-                                       oos.writeObject(null);
-                               }
-                               oos.writeObject(object);
-                       }
-                       finally
-                       {
-                               try
-                               {
-                                       IOUtils.close(oos);
-                               }
-                               finally
-                               {
-                                       out.close();
-                               }
-                       }
-                       return out.toByteArray();
-               }
-               catch (Exception e)
-               {
-                       log.error("Error serializing object " + 
object.getClass() + " [object=" + object + "]",
-                               e);
-               }
-               return null;
-       }
-
-       /**
         * Sets the strategy for determining the sizes of objects.
         * 
         * @param objectSizeOfStrategy
@@ -563,27 +404,6 @@ public class WicketObjects
        }
 
        /**
-        * Configure this utility class to use the provided {@link 
IObjectStreamFactory} instance.
-        * 
-        * @param objectStreamFactory
-        *            The factory instance to use. If you pass in null, the
-        *            {@link DefaultObjectStreamFactory default} will be set 
(again). Pass null to reset
-        *            to the default.
-        */
-       public static void setObjectStreamFactory(IObjectStreamFactory 
objectStreamFactory)
-       {
-               if (objectStreamFactory == null)
-               {
-                       WicketObjects.objectStreamFactory = new 
IObjectStreamFactory.DefaultObjectStreamFactory();
-               }
-               else
-               {
-                       WicketObjects.objectStreamFactory = objectStreamFactory;
-               }
-               log.info("using " + WicketObjects.objectStreamFactory + " for 
creating object streams");
-       }
-
-       /**
         * Computes the size of an object. Note that this is an estimation, 
never an absolute accurate
         * size.
         * 

Modified: 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java?rev=1133952&r1=1133951&r2=1133952&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
 (original)
+++ 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
 Thu Jun  9 15:50:28 2011
@@ -18,7 +18,6 @@ package org.apache.wicket.page;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -31,8 +30,8 @@ import org.apache.wicket.pageStore.IData
 import org.apache.wicket.pageStore.IPageStore;
 import org.apache.wicket.pageStore.memory.DummyPageManagerContext;
 import org.apache.wicket.serialize.java.JavaSerializer;
-import org.apache.wicket.util.lang.WicketObjects;
 import org.apache.wicket.versioning.InMemoryPageStore;
+import org.junit.Assert;
 import org.junit.Test;
 
 /**
@@ -40,6 +39,8 @@ import org.junit.Test;
  */
 public class PersistentPageManagerTest
 {
+       private static final String APP_NAME = "test_app";
+
        /**
         * WICKET-3470
         * 
@@ -53,7 +54,7 @@ public class PersistentPageManagerTest
        public void serializationOutsideWicketLifecyle() throws IOException, 
ClassNotFoundException
        {
                // create IPageManager (with IPageStore) and store a page 
instance
-               IPageManager pageManager = newPersistentPageManager("test_app");
+               IPageManager pageManager = newPersistentPageManager(APP_NAME);
                TestPage toSerializePage = new TestPage();
                pageManager.touchPage(toSerializePage);
                pageManager.commitRequest();
@@ -65,7 +66,7 @@ public class PersistentPageManagerTest
                pageManager.destroy();
 
                // simulate persisting of the http sessions initiated by the 
web container
-               byte[] serializedSessionEntry = 
WicketObjects.objectToByteArray(sessionEntry);
+               byte[] serializedSessionEntry = new 
JavaSerializer(APP_NAME).serialize(sessionEntry);
                assertNotNull("Wicket needs to be able to serialize the session 
entry",
                        serializedSessionEntry);
 
@@ -75,11 +76,10 @@ public class PersistentPageManagerTest
                        serializedSessionEntry));
 
                // WicketFilter is not initialized so there is no Application 
available yet
-               if (Application.exists())
-               {
-                       System.err.println("==================DEBUG  
==========" + Application.get().getName());
-               }
-               assertNull("Worker thread should be unaware of Wicket 
application", in.readObject());
+               Assert.assertFalse("Worker thread should be unaware of Wicket 
application",
+                       Application.exists());
+
+               assertEquals(APP_NAME, in.readObject());
 
                // without available IPageStore the read SessionEntry holds
                // the IManageablePage itself, not SerializedPage
@@ -90,7 +90,7 @@ public class PersistentPageManagerTest
 
                // provide new IPageStore which will read IManageablePage's or 
SerializedPage's
                // from the SessionEntry's
-               IPageManager newPageManager = 
newPersistentPageManager("test_app");
+               IPageManager newPageManager = 
newPersistentPageManager(APP_NAME);
                newPageManager.getContext().setSessionAttribute(null, 
loadedSessionEntry);
 
                TestPage deserializedPage = 
(TestPage)newPageManager.getPage(toSerializePage.getPageId());


Reply via email to