Updated Branches:
  refs/heads/wicket-1.5.x 19d06d27c -> 486b7eb88

WICKET-4812 Make SerializationChecker easier for extending so custom checks can 
be added to it

Rename ObjectChecker to CheckingObjectOutputStream to make it more clear that 
it is not an implementation of IObjectChecker.
Simplify JavaSerializer to use CheckingObjectOutputStream directly without 
another ObjectOutputStream as adapter.


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/486b7eb8
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/486b7eb8
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/486b7eb8

Branch: refs/heads/wicket-1.5.x
Commit: 486b7eb88df5fa11bb7892f6e135fb1b62c4a6a3
Parents: 19d06d2
Author: Martin Tzvetanov Grigorov <mgrigo...@apache.org>
Authored: Wed Oct 17 11:17:12 2012 +0200
Committer: Martin Tzvetanov Grigorov <mgrigo...@apache.org>
Committed: Wed Oct 17 11:17:12 2012 +0200

----------------------------------------------------------------------
 .../wicket/serialize/java/JavaSerializer.java      |   25 +-
 .../apache/wicket/util/io/SerializableChecker.java |   27 +-
 .../checker/CheckingObjectOutputStream.java        |  723 +++++++++++++++
 .../wicket/util/objects/checker/ObjectChecker.java |  709 --------------
 .../wicket/util/io/SerializableCheckerTest.java    |    6 +-
 5 files changed, 764 insertions(+), 726 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/486b7eb8/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
 
b/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
index e37666b..7eebf32 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/serialize/java/JavaSerializer.java
@@ -34,6 +34,7 @@ import org.apache.wicket.serialize.ISerializer;
 import org.apache.wicket.settings.IApplicationSettings;
 import org.apache.wicket.util.io.IOUtils;
 import org.apache.wicket.util.io.SerializableChecker;
+import org.apache.wicket.util.objects.checker.CheckingObjectOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,8 +44,6 @@ import org.slf4j.LoggerFactory;
  * 
  * 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
 {
@@ -171,7 +170,7 @@ public class JavaSerializer implements ISerializer
         */
        protected ObjectOutputStream newObjectOutputStream(OutputStream out) 
throws IOException
        {
-               return new CheckerObjectOutputStream(out);
+               return new SerializationCheckingObjectOutputStream(out);
        }
 
        /**
@@ -231,15 +230,23 @@ public class JavaSerializer implements ISerializer
        }
        /**
         * Write objects to the wrapped output stream and log a meaningful 
message for serialization
-        * problems
+        * problems.
+        *
+        * <p>
+        *     Note: the checking functionality is used only if the 
serialization fails with NotSerializableException.
+        *     This is done so to save some CPU time to make the checks for no 
reason.
+        * </p>
         */
-       private static class CheckerObjectOutputStream extends 
ObjectOutputStream
+       private static class SerializationCheckingObjectOutputStream extends 
ObjectOutputStream
        {
+               private final OutputStream outputStream;
+
                private final ObjectOutputStream oos;
 
-               public CheckerObjectOutputStream(OutputStream out) throws 
IOException
+               private SerializationCheckingObjectOutputStream(OutputStream 
outputStream) throws IOException
                {
-                       oos = new ObjectOutputStream(out);
+                       this.outputStream = outputStream;
+                       oos = new ObjectOutputStream(outputStream);
                }
 
                @Override
@@ -251,11 +258,11 @@ public class JavaSerializer implements ISerializer
                        }
                        catch (NotSerializableException nsx)
                        {
-                               if (SerializableChecker.isAvailable())
+                               if (CheckingObjectOutputStream.isAvailable())
                                {
                                        // trigger serialization again, but 
this time gather
                                        // some more info
-                                       new 
SerializableChecker(nsx).writeObject(obj);
+                                       new SerializableChecker(outputStream, 
nsx).writeObject(obj);
                                        // if we get here, we didn't fail, 
while we
                                        // should;
                                        throw nsx;

http://git-wip-us.apache.org/repos/asf/wicket/blob/486b7eb8/wicket-core/src/main/java/org/apache/wicket/util/io/SerializableChecker.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/util/io/SerializableChecker.java 
b/wicket-core/src/main/java/org/apache/wicket/util/io/SerializableChecker.java
index 8353bd9..a6eff20 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/util/io/SerializableChecker.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/util/io/SerializableChecker.java
@@ -18,25 +18,27 @@ package org.apache.wicket.util.io;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
+import java.io.OutputStream;
 import java.io.Serializable;
 import java.lang.reflect.Proxy;
 
 import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.util.io.ByteArrayOutputStream;
 import org.apache.wicket.util.objects.checker.AbstractObjectChecker;
-import org.apache.wicket.util.objects.checker.ObjectChecker;
+import org.apache.wicket.util.objects.checker.CheckingObjectOutputStream;
 
 
 /**
  * Utility class that analyzes objects for non-serializable nodes. Construct, 
then call
  * {@link #writeObject(Object)} with the object you want to check. When a 
non-serializable object is
- * found, a {@link WicketNotSerializableException} is thrown with a message 
that shows the trace up
+ * found, a {@link ObjectCheckException} is thrown with a message that shows 
the trace up
  * to the not-serializable object. The exception is thrown for the first 
non-serializable instance
  * it encounters, so multiple problems will not be shown.
  *
  * @author eelcohillenius
  * @author Al Maw
  */
-public class SerializableChecker extends ObjectChecker
+public class SerializableChecker extends CheckingObjectOutputStream
 {
        /**
         * Exception that is thrown when a non-serializable object was found.
@@ -112,7 +114,22 @@ public class SerializableChecker extends ObjectChecker
         */
        public SerializableChecker(NotSerializableException exception) throws 
IOException
        {
-               super(new ObjectSerializationChecker(exception));
+               this(new ByteArrayOutputStream(), exception);
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param exception
+        *      exception that should be set as the cause when throwing a new 
exception
+        * @param outputStream
+        *      the output stream where the serialized object will be written 
upon successful check
+        *
+        * @throws IOException
+        */
+       public SerializableChecker(final OutputStream outputStream, 
NotSerializableException exception) throws IOException
+       {
+               super(outputStream, new ObjectSerializationChecker(exception));
        }
 
        /**
@@ -125,6 +142,6 @@ public class SerializableChecker extends ObjectChecker
        @Deprecated
        public static boolean isAvailable()
        {
-               return ObjectChecker.isAvailable();
+               return CheckingObjectOutputStream.isAvailable();
        }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/486b7eb8/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/CheckingObjectOutputStream.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/CheckingObjectOutputStream.java
 
b/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/CheckingObjectOutputStream.java
new file mode 100644
index 0000000..7071980
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/CheckingObjectOutputStream.java
@@ -0,0 +1,723 @@
+/*
+ * 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.wicket.util.objects.checker;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.ObjectStreamField;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.util.lang.Classes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Checks an object tree during serialization for wrong state by delegating 
the work
+ * to the used {@link IObjectChecker IObjectChecker}s.
+ * <p>
+ * As this class depends heavily on JDK's serialization internals using 
introspection, analyzing may
+ * not be possible, for instance when the runtime environment does not have 
sufficient rights to set
+ * fields accessible that would otherwise be hidden. You should call
+ * {@link CheckingObjectOutputStream#isAvailable()} to see whether this class 
can operate properly.
+ *
+ *
+ * An ObjectOutputStream that uses {@link IObjectChecker IObjectChecker}s to 
check the
+ * state of the object before serializing it. If the checker returns
+ * {@link 
org.apache.wicket.util.objects.checker.IObjectChecker.Result.Status#FAILURE}
+ * then the serialization process is stopped and the error is logged.
+ * </p>
+ */
+public class CheckingObjectOutputStream extends ObjectOutputStream
+{
+       private static final Logger log = 
LoggerFactory.getLogger(CheckingObjectOutputStream.class);
+
+       public static class ObjectCheckException extends WicketRuntimeException
+       {
+               public ObjectCheckException(String message, Throwable cause)
+               {
+                       super(message, cause);
+               }
+       }
+
+       /**
+        * Does absolutely nothing.
+        */
+       private static class NoopOutputStream extends OutputStream
+       {
+               @Override
+               public void close()
+               {
+               }
+
+               @Override
+               public void flush()
+               {
+               }
+
+               @Override
+               public void write(byte[] b)
+               {
+               }
+
+               @Override
+               public void write(byte[] b, int i, int l)
+               {
+               }
+
+               @Override
+               public void write(int b)
+               {
+               }
+       }
+
+       private static abstract class ObjectOutputAdaptor implements 
ObjectOutput
+       {
+               public void close() throws IOException
+               {
+               }
+
+               public void flush() throws IOException
+               {
+               }
+
+               public void write(byte[] b) throws IOException
+               {
+               }
+
+               public void write(byte[] b, int off, int len) throws IOException
+               {
+               }
+
+               public void write(int b) throws IOException
+               {
+               }
+
+               public void writeBoolean(boolean v) throws IOException
+               {
+               }
+
+               public void writeByte(int v) throws IOException
+               {
+               }
+
+               public void writeBytes(String s) throws IOException
+               {
+               }
+
+               public void writeChar(int v) throws IOException
+               {
+               }
+
+               public void writeChars(String s) throws IOException
+               {
+               }
+
+               public void writeDouble(double v) throws IOException
+               {
+               }
+
+               public void writeFloat(float v) throws IOException
+               {
+               }
+
+               public void writeInt(int v) throws IOException
+               {
+               }
+
+               public void writeLong(long v) throws IOException
+               {
+               }
+
+               public void writeShort(int v) throws IOException
+               {
+               }
+
+               public void writeUTF(String str) throws IOException
+               {
+               }
+       }
+
+       /** Holds information about the field and the resulting object being 
traced. */
+       private static final class TraceSlot
+       {
+               private final String fieldDescription;
+
+               private final Object object;
+
+               TraceSlot(Object object, String fieldDescription)
+               {
+                       this.object = object;
+                       this.fieldDescription = fieldDescription;
+               }
+
+               @Override
+               public String toString()
+               {
+                       return object.getClass() + " - " + fieldDescription;
+               }
+       }
+
+       private static final NoopOutputStream DUMMY_OUTPUT_STREAM = new 
NoopOutputStream();
+
+       /** Whether we can execute the tests. If false, check will just return. 
*/
+       private static boolean available = true;
+
+       // this hack - accessing the serialization API through introspection - 
is
+       // the only way to use Java serialization for our purposes without 
writing
+       // the whole thing from scratch (and even then, it would be limited). 
This
+       // way of working is of course fragile for internal API changes, but as 
we
+       // do an extra check on availability and we report when we can't use 
this
+       // introspection fu, we'll find out soon enough and clients on this 
class
+       // can fall back on Java's default exception for serialization errors 
(which
+       // sucks and is the main reason for this attempt).
+       private static Method LOOKUP_METHOD;
+
+       private static Method GET_CLASS_DATA_LAYOUT_METHOD;
+
+       private static Method GET_NUM_OBJ_FIELDS_METHOD;
+
+       private static Method GET_OBJ_FIELD_VALUES_METHOD;
+
+       private static Method GET_FIELD_METHOD;
+
+       private static Method HAS_WRITE_REPLACE_METHOD_METHOD;
+
+       private static Method INVOKE_WRITE_REPLACE_METHOD;
+
+       static
+       {
+               try
+               {
+                       LOOKUP_METHOD = 
ObjectStreamClass.class.getDeclaredMethod("lookup", new Class[] {
+                                       Class.class, Boolean.TYPE });
+                       LOOKUP_METHOD.setAccessible(true);
+
+                       GET_CLASS_DATA_LAYOUT_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
+                                       "getClassDataLayout", (Class[])null);
+                       GET_CLASS_DATA_LAYOUT_METHOD.setAccessible(true);
+
+                       GET_NUM_OBJ_FIELDS_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
+                                       "getNumObjFields", (Class[])null);
+                       GET_NUM_OBJ_FIELDS_METHOD.setAccessible(true);
+
+                       GET_OBJ_FIELD_VALUES_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
+                                       "getObjFieldValues", new Class[] { 
Object.class, Object[].class });
+                       GET_OBJ_FIELD_VALUES_METHOD.setAccessible(true);
+
+                       GET_FIELD_METHOD = 
ObjectStreamField.class.getDeclaredMethod("getField", (Class[])null);
+                       GET_FIELD_METHOD.setAccessible(true);
+
+                       HAS_WRITE_REPLACE_METHOD_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
+                                       "hasWriteReplaceMethod", (Class[])null);
+                       HAS_WRITE_REPLACE_METHOD_METHOD.setAccessible(true);
+
+                       INVOKE_WRITE_REPLACE_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
+                                       "invokeWriteReplace", new Class[] { 
Object.class });
+                       INVOKE_WRITE_REPLACE_METHOD.setAccessible(true);
+               }
+               catch (Exception e)
+               {
+                       log.warn("SerializableChecker not available", e);
+                       available = false;
+               }
+       }
+
+       private final IObjectChecker[] checkers;
+
+       /**
+        * Gets whether we can execute the tests. If false, calling {@link 
#check(Object)} will just
+        * return and you are advised to rely on the {@link 
java.io.NotSerializableException}. Clients are
+        * advised to call this method prior to calling the check method.
+        *
+        * @return whether security settings and underlying API etc allow for 
accessing the
+        *         serialization API using introspection
+        */
+       public static boolean isAvailable()
+       {
+               return available;
+       }
+
+       /**
+        * The output stream where the serialized object will be written upon 
successful check
+        */
+       private final ObjectOutputStream out;
+
+       /** object stack with the trace path. */
+       private final LinkedList<TraceSlot> traceStack = new 
LinkedList<TraceSlot>();
+
+       /** set for checking circular references. */
+       private final Map<Object, Object> checked = new IdentityHashMap<Object, 
Object>();
+
+       /** string stack with current names pushed. */
+       private final LinkedList<CharSequence> nameStack = new 
LinkedList<CharSequence>();
+
+       /** root object being analyzed. */
+       private Object root;
+
+       /** set of classes that had no writeObject methods at lookup (to avoid 
repeated checking) */
+       private final Set<Class<?>> writeObjectMethodMissing = new 
HashSet<Class<?>>();
+
+       /** current simple field name. */
+       private CharSequence simpleName = "";
+
+       /** current full field description. */
+       private String fieldDescription;
+
+       private final Stack<Object> stack = new Stack<Object>();
+
+       /**
+        * Constructor.
+        *
+        * @param outputStream
+        *      the output stream where the serialized object will be written 
upon successful check
+        * @param checkers
+        *      the {@link IObjectChecker checkers} that will actually check 
the objects
+        * @throws IOException
+        * @throws SecurityException
+        */
+       public CheckingObjectOutputStream(final OutputStream outputStream, 
final IObjectChecker... checkers) throws IOException, SecurityException
+       {
+               this.out = new ObjectOutputStream(outputStream);
+               this.checkers = checkers;
+       }
+
+       private void check(Object obj)
+       {
+               if (obj == null)
+               {
+                       return;
+               }
+
+               try
+               {
+                       if (stack.contains(obj))
+                       {
+                               return;
+                       }
+               }
+               catch (RuntimeException e)
+               {
+                       log.warn("Wasn't possible to check the object '{}' 
possible due an problematic " +
+                                       "implementation of equals method", 
obj.getClass());
+                       /*
+                        * Can't check if this obj were in stack, giving up 
because we don't want to throw an
+                        * invaluable exception to user. The main goal of this 
checker is to find non
+                        * serializable data
+                        */
+                       return;
+               }
+
+               stack.push(obj);
+               try
+               {
+                       internalCheck(obj);
+               }
+               finally
+               {
+                       stack.pop();
+               }
+       }
+
+       private void internalCheck(Object obj)
+       {
+               if (obj == null)
+               {
+                       return;
+               }
+
+               Class<?> cls = obj.getClass();
+               nameStack.add(simpleName);
+               traceStack.add(new TraceSlot(obj, fieldDescription));
+
+               for (IObjectChecker checker : checkers)
+               {
+                       IObjectChecker.Result result = checker.check(obj);
+                       if (result.status == 
IObjectChecker.Result.Status.FAILURE)
+                       {
+                               String prettyPrintMessage = 
toPrettyPrintedStack(Classes.name(cls));
+                               String exceptionMessage = result.reason + '\n' 
+ prettyPrintMessage;
+                               throw new 
ObjectCheckException(exceptionMessage, result.cause);
+                       }
+               }
+
+               ObjectStreamClass desc;
+               for (;;)
+               {
+                       try
+                       {
+                               desc = 
(ObjectStreamClass)LOOKUP_METHOD.invoke(null, cls, Boolean.TRUE);
+                               Class<?> repCl;
+                               if 
(!(Boolean)HAS_WRITE_REPLACE_METHOD_METHOD.invoke(desc, (Object[])null) ||
+                                               (obj = 
INVOKE_WRITE_REPLACE_METHOD.invoke(desc, obj)) == null ||
+                                               (repCl = obj.getClass()) == cls)
+                               {
+                                       break;
+                               }
+                               cls = repCl;
+                       }
+                       catch (IllegalAccessException e)
+                       {
+                               throw new RuntimeException(e);
+                       }
+                       catch (InvocationTargetException e)
+                       {
+                               throw new RuntimeException(e);
+                       }
+               }
+
+               if (cls.isPrimitive())
+               {
+                       // skip
+               }
+               else if (cls.isArray())
+               {
+                       checked.put(obj, null);
+                       Class<?> ccl = cls.getComponentType();
+                       if (!(ccl.isPrimitive()))
+                       {
+                               Object[] objs = (Object[])obj;
+                               for (int i = 0; i < objs.length; i++)
+                               {
+                                       CharSequence arrayPos = new 
StringBuilder(4).append('[').append(i).append(']');
+                                       simpleName = arrayPos;
+                                       fieldDescription += arrayPos;
+                                       check(objs[i]);
+                               }
+                       }
+               }
+               else if (obj instanceof Externalizable && 
(!Proxy.isProxyClass(cls)))
+               {
+                       Externalizable extObj = (Externalizable)obj;
+                       try
+                       {
+                               extObj.writeExternal(new ObjectOutputAdaptor()
+                               {
+                                       private int count = 0;
+
+                                       public void writeObject(Object 
streamObj) throws IOException
+                                       {
+                                               // Check for circular reference.
+                                               if 
(checked.containsKey(streamObj))
+                                               {
+                                                       return;
+                                               }
+
+                                               checked.put(streamObj, null);
+                                               CharSequence arrayPos = new 
StringBuilder(10).append("[write:").append(count++).append(']');
+                                               simpleName = arrayPos;
+                                               fieldDescription += arrayPos;
+
+                                               check(streamObj);
+                                       }
+                               });
+                       }
+                       catch (Exception e)
+                       {
+                               if (e instanceof ObjectCheckException)
+                               {
+                                       throw (ObjectCheckException)e;
+                               }
+                               log.warn("Error delegating to Externalizable : 
{}, path: {}", e.getMessage(), currentPath());
+                       }
+               }
+               else
+               {
+                       Method writeObjectMethod = null;
+                       if (writeObjectMethodMissing.contains(cls) == false)
+                       {
+                               try
+                               {
+                                       writeObjectMethod = 
cls.getDeclaredMethod("writeObject",
+                                                       new Class[] { 
java.io.ObjectOutputStream.class });
+                               }
+                               catch (SecurityException e)
+                               {
+                                       // we can't access / set accessible to 
true
+                                       writeObjectMethodMissing.add(cls);
+                               }
+                               catch (NoSuchMethodException e)
+                               {
+                                       // cls doesn't have that method
+                                       writeObjectMethodMissing.add(cls);
+                               }
+                       }
+
+                       final Object original = obj;
+                       if (writeObjectMethod != null)
+                       {
+                               class InterceptingObjectOutputStream extends 
ObjectOutputStream
+                               {
+                                       private int counter;
+
+                                       InterceptingObjectOutputStream() throws 
IOException
+                                       {
+                                               super(DUMMY_OUTPUT_STREAM);
+                                               enableReplaceObject(true);
+                                       }
+
+                                       @Override
+                                       protected Object replaceObject(Object 
streamObj) throws IOException
+                                       {
+                                               if (streamObj == original)
+                                               {
+                                                       return streamObj;
+                                               }
+
+                                               counter++;
+                                               // Check for circular reference.
+                                               if 
(checked.containsKey(streamObj))
+                                               {
+                                                       return null;
+                                               }
+
+                                               checked.put(streamObj, null);
+                                               CharSequence arrayPos = new 
StringBuilder(10).append("[write:").append(counter).append(']');
+                                               simpleName = arrayPos;
+                                               fieldDescription += arrayPos;
+                                               check(streamObj);
+                                               return streamObj;
+                                       }
+                               }
+                               try
+                               {
+                                       InterceptingObjectOutputStream ioos = 
new InterceptingObjectOutputStream();
+                                       ioos.writeObject(obj);
+                               }
+                               catch (Exception e)
+                               {
+                                       if (e instanceof ObjectCheckException)
+                                       {
+                                               throw (ObjectCheckException)e;
+                                       }
+                                       log.warn("error delegating to 
writeObject : {}, path: {}", e.getMessage(), currentPath());
+                               }
+                       }
+                       else
+                       {
+                               Object[] slots;
+                               try
+                               {
+                                       slots = 
(Object[])GET_CLASS_DATA_LAYOUT_METHOD.invoke(desc, (Object[])null);
+                               }
+                               catch (Exception e)
+                               {
+                                       throw new RuntimeException(e);
+                               }
+                               for (Object slot : slots)
+                               {
+                                       ObjectStreamClass slotDesc;
+                                       try
+                                       {
+                                               Field descField = 
slot.getClass().getDeclaredField("desc");
+                                               descField.setAccessible(true);
+                                               slotDesc = 
(ObjectStreamClass)descField.get(slot);
+                                       }
+                                       catch (Exception e)
+                                       {
+                                               throw new RuntimeException(e);
+                                       }
+                                       checked.put(obj, null);
+                                       checkFields(obj, slotDesc);
+                               }
+                       }
+               }
+
+               traceStack.removeLast();
+               nameStack.removeLast();
+       }
+
+       private void checkFields(Object obj, ObjectStreamClass desc)
+       {
+               int numFields;
+               try
+               {
+                       numFields = 
(Integer)GET_NUM_OBJ_FIELDS_METHOD.invoke(desc, (Object[])null);
+               }
+               catch (IllegalAccessException e)
+               {
+                       throw new RuntimeException(e);
+               }
+               catch (InvocationTargetException e)
+               {
+                       throw new RuntimeException(e);
+               }
+
+               if (numFields > 0)
+               {
+                       int numPrimFields;
+                       ObjectStreamField[] fields = desc.getFields();
+                       Object[] objVals = new Object[numFields];
+                       numPrimFields = fields.length - objVals.length;
+                       try
+                       {
+                               GET_OBJ_FIELD_VALUES_METHOD.invoke(desc, obj, 
objVals);
+                       }
+                       catch (IllegalAccessException e)
+                       {
+                               throw new RuntimeException(e);
+                       }
+                       catch (InvocationTargetException e)
+                       {
+                               throw new RuntimeException(e);
+                       }
+                       for (int i = 0; i < objVals.length; i++)
+                       {
+                               if (objVals[i] instanceof String || objVals[i] 
instanceof Number ||
+                                               objVals[i] instanceof Date || 
objVals[i] instanceof Boolean ||
+                                               objVals[i] instanceof Class)
+                               {
+                                       // filter out common cases
+                                       continue;
+                               }
+
+                               // Check for circular reference.
+                               if (checked.containsKey(objVals[i]))
+                               {
+                                       continue;
+                               }
+
+                               ObjectStreamField fieldDesc = 
fields[numPrimFields + i];
+                               Field field;
+                               try
+                               {
+                                       field = 
(Field)GET_FIELD_METHOD.invoke(fieldDesc, (Object[])null);
+                               }
+                               catch (IllegalAccessException e)
+                               {
+                                       throw new RuntimeException(e);
+                               }
+                               catch (InvocationTargetException e)
+                               {
+                                       throw new RuntimeException(e);
+                               }
+
+                               simpleName = field.getName();
+                               fieldDescription = field.toString();
+                               check(objVals[i]);
+                       }
+               }
+       }
+
+       /**
+        * @return name from root to current node concatenated with slashes
+        */
+       private StringBuilder currentPath()
+       {
+               StringBuilder b = new StringBuilder();
+               for (Iterator<CharSequence> it = nameStack.iterator(); 
it.hasNext();)
+               {
+                       b.append(it.next());
+                       if (it.hasNext())
+                       {
+                               b.append('/');
+                       }
+               }
+               return b;
+       }
+
+       /**
+        * Dump with indentation.
+        *
+        * @param type
+        *            the type that couldn't be serialized
+        * @return A very pretty dump
+        */
+       protected final String toPrettyPrintedStack(String type)
+       {
+               StringBuilder result = new StringBuilder(512);
+               StringBuilder spaces = new StringBuilder(32);
+               result.append("A problem occurred while checking object with 
type: ");
+               result.append(type);
+               result.append("\nField hierarchy is:");
+               for (TraceSlot slot : traceStack)
+               {
+                       spaces.append(' ').append(' ');
+                       
result.append('\n').append(spaces).append(slot.fieldDescription);
+                       result.append(" 
[class=").append(Classes.name(slot.object.getClass()));
+                       if (slot.object instanceof Component)
+                       {
+                               Component component = (Component)slot.object;
+                               result.append(", 
path=").append(component.getPath());
+                       }
+                       result.append(']');
+               }
+               result.append(" <----- field that is causing the problem");
+               return result.toString();
+       }
+
+       /**
+        * @see java.io.ObjectOutputStream#writeObjectOverride(java.lang.Object)
+        */
+       @Override
+       protected final void writeObjectOverride(Object obj) throws IOException
+       {
+               if (!available)
+               {
+                       return;
+               }
+               root = obj;
+               if (fieldDescription == null)
+               {
+                       fieldDescription = (root instanceof Component) ? 
((Component)root).getPath() : "";
+               }
+
+               check(root);
+               out.writeObject(obj);
+       }
+
+       /**
+        * @see java.io.ObjectOutputStream#reset()
+        */
+       @Override
+       public void reset() throws IOException
+       {
+               root = null;
+               checked.clear();
+               fieldDescription = null;
+               simpleName = null;
+               traceStack.clear();
+               nameStack.clear();
+               writeObjectMethodMissing.clear();
+       }
+
+       @Override
+       public void close() throws IOException
+       {
+               // do not call super.close() because SerializableChecker uses 
ObjectOutputStream's no-arg constructor
+
+               // just null-ify the declared members
+               reset();
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/486b7eb8/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/ObjectChecker.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/ObjectChecker.java
 
b/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/ObjectChecker.java
deleted file mode 100644
index 3109981..0000000
--- 
a/wicket-core/src/main/java/org/apache/wicket/util/objects/checker/ObjectChecker.java
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * 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.wicket.util.objects.checker;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectOutput;
-import java.io.ObjectOutputStream;
-import java.io.ObjectStreamClass;
-import java.io.ObjectStreamField;
-import java.io.OutputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.WicketRuntimeException;
-import org.apache.wicket.util.lang.Classes;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Checks an object tree during serialization for wrong state by delegating 
the work
- * to the used {@link IObjectChecker IObjectChecker}s.
- * <p>
- * As this class depends heavily on JDK's serialization internals using 
introspection, analyzing may
- * not be possible, for instance when the runtime environment does not have 
sufficient rights to set
- * fields accessible that would otherwise be hidden. You should call
- * {@link ObjectChecker#isAvailable()} to see whether this class can operate 
properly.
- * </p>
- */
-public class ObjectChecker extends ObjectOutputStream
-{
-       private static final Logger log = 
LoggerFactory.getLogger(ObjectChecker.class);
-
-       public static class ObjectCheckException extends WicketRuntimeException
-       {
-               public ObjectCheckException(String message, Throwable cause)
-               {
-                       super(message, cause);
-               }
-       }
-
-       /**
-        * Does absolutely nothing.
-        */
-       private static class NoopOutputStream extends OutputStream
-       {
-               @Override
-               public void close()
-               {
-               }
-
-               @Override
-               public void flush()
-               {
-               }
-
-               @Override
-               public void write(byte[] b)
-               {
-               }
-
-               @Override
-               public void write(byte[] b, int i, int l)
-               {
-               }
-
-               @Override
-               public void write(int b)
-               {
-               }
-       }
-
-       private static abstract class ObjectOutputAdaptor implements 
ObjectOutput
-       {
-
-               public void close() throws IOException
-               {
-               }
-
-               public void flush() throws IOException
-               {
-               }
-
-               public void write(byte[] b) throws IOException
-               {
-               }
-
-               public void write(byte[] b, int off, int len) throws IOException
-               {
-               }
-
-               public void write(int b) throws IOException
-               {
-               }
-
-               public void writeBoolean(boolean v) throws IOException
-               {
-               }
-
-               public void writeByte(int v) throws IOException
-               {
-               }
-
-               public void writeBytes(String s) throws IOException
-               {
-               }
-
-               public void writeChar(int v) throws IOException
-               {
-               }
-
-               public void writeChars(String s) throws IOException
-               {
-               }
-
-               public void writeDouble(double v) throws IOException
-               {
-               }
-
-               public void writeFloat(float v) throws IOException
-               {
-               }
-
-               public void writeInt(int v) throws IOException
-               {
-               }
-
-               public void writeLong(long v) throws IOException
-               {
-               }
-
-               public void writeShort(int v) throws IOException
-               {
-               }
-
-               public void writeUTF(String str) throws IOException
-               {
-               }
-       }
-
-       /** Holds information about the field and the resulting object being 
traced. */
-       private static final class TraceSlot
-       {
-               private final String fieldDescription;
-
-               private final Object object;
-
-               TraceSlot(Object object, String fieldDescription)
-               {
-                       this.object = object;
-                       this.fieldDescription = fieldDescription;
-               }
-
-               @Override
-               public String toString()
-               {
-                       return object.getClass() + " - " + fieldDescription;
-               }
-       }
-
-       private static final NoopOutputStream DUMMY_OUTPUT_STREAM = new 
NoopOutputStream();
-
-       /** Whether we can execute the tests. If false, check will just return. 
*/
-       private static boolean available = true;
-
-       // this hack - accessing the serialization API through introspection - 
is
-       // the only way to use Java serialization for our purposes without 
writing
-       // the whole thing from scratch (and even then, it would be limited). 
This
-       // way of working is of course fragile for internal API changes, but as 
we
-       // do an extra check on availability and we report when we can't use 
this
-       // introspection fu, we'll find out soon enough and clients on this 
class
-       // can fall back on Java's default exception for serialization errors 
(which
-       // sucks and is the main reason for this attempt).
-       private static Method LOOKUP_METHOD;
-
-       private static Method GET_CLASS_DATA_LAYOUT_METHOD;
-
-       private static Method GET_NUM_OBJ_FIELDS_METHOD;
-
-       private static Method GET_OBJ_FIELD_VALUES_METHOD;
-
-       private static Method GET_FIELD_METHOD;
-
-       private static Method HAS_WRITE_REPLACE_METHOD_METHOD;
-
-       private static Method INVOKE_WRITE_REPLACE_METHOD;
-
-       static
-       {
-               try
-               {
-                       LOOKUP_METHOD = 
ObjectStreamClass.class.getDeclaredMethod("lookup", new Class[] {
-                                       Class.class, Boolean.TYPE });
-                       LOOKUP_METHOD.setAccessible(true);
-
-                       GET_CLASS_DATA_LAYOUT_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
-                                       "getClassDataLayout", (Class[])null);
-                       GET_CLASS_DATA_LAYOUT_METHOD.setAccessible(true);
-
-                       GET_NUM_OBJ_FIELDS_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
-                                       "getNumObjFields", (Class[])null);
-                       GET_NUM_OBJ_FIELDS_METHOD.setAccessible(true);
-
-                       GET_OBJ_FIELD_VALUES_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
-                                       "getObjFieldValues", new Class[] { 
Object.class, Object[].class });
-                       GET_OBJ_FIELD_VALUES_METHOD.setAccessible(true);
-
-                       GET_FIELD_METHOD = 
ObjectStreamField.class.getDeclaredMethod("getField", (Class[])null);
-                       GET_FIELD_METHOD.setAccessible(true);
-
-                       HAS_WRITE_REPLACE_METHOD_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
-                                       "hasWriteReplaceMethod", (Class[])null);
-                       HAS_WRITE_REPLACE_METHOD_METHOD.setAccessible(true);
-
-                       INVOKE_WRITE_REPLACE_METHOD = 
ObjectStreamClass.class.getDeclaredMethod(
-                                       "invokeWriteReplace", new Class[] { 
Object.class });
-                       INVOKE_WRITE_REPLACE_METHOD.setAccessible(true);
-               }
-               catch (Exception e)
-               {
-                       log.warn("SerializableChecker not available", e);
-                       available = false;
-               }
-       }
-
-       private final IObjectChecker[] checkers;
-
-       /**
-        * Gets whether we can execute the tests. If false, calling {@link 
#check(Object)} will just
-        * return and you are advised to rely on the {@link 
java.io.NotSerializableException}. Clients are
-        * advised to call this method prior to calling the check method.
-        *
-        * @return whether security settings and underlying API etc allow for 
accessing the
-        *         serialization API using introspection
-        */
-       public static boolean isAvailable()
-       {
-               return available;
-       }
-
-       /** object stack with the trace path. */
-       private final LinkedList<TraceSlot> traceStack = new 
LinkedList<TraceSlot>();
-
-       /** set for checking circular references. */
-       private final Map<Object, Object> checked = new IdentityHashMap<Object, 
Object>();
-
-       /** string stack with current names pushed. */
-       private final LinkedList<CharSequence> nameStack = new 
LinkedList<CharSequence>();
-
-       /** root object being analyzed. */
-       private Object root;
-
-       /** set of classes that had no writeObject methods at lookup (to avoid 
repeated checking) */
-       private final Set<Class<?>> writeObjectMethodMissing = new 
HashSet<Class<?>>();
-
-       /** current simple field name. */
-       private CharSequence simpleName = "";
-
-       /** current full field description. */
-       private String fieldDescription;
-
-       private final Stack<Object> stack = new Stack<Object>();
-
-       /**
-        * Constructor.
-        *
-        * @param checkers
-        *      the {@link IObjectChecker checkers} that will actually check 
the objects
-        * @throws java.io.IOException
-        * @throws SecurityException
-        */
-       public ObjectChecker(final IObjectChecker... checkers) throws 
IOException, SecurityException
-       {
-               this.checkers = checkers;
-       }
-
-       private void check(Object obj)
-       {
-               if (obj == null)
-               {
-                       return;
-               }
-
-               try
-               {
-                       if (stack.contains(obj))
-                       {
-                               return;
-                       }
-               }
-               catch (RuntimeException e)
-               {
-                       log.warn("Wasn't possible to check the object '{}' 
possible due an problematic " +
-                                       "implementation of equals method", 
obj.getClass());
-                       /*
-                        * Can't check if this obj were in stack, giving up 
because we don't want to throw an
-                        * invaluable exception to user. The main goal of this 
checker is to find non
-                        * serializable data
-                        */
-                       return;
-               }
-
-               stack.push(obj);
-               try
-               {
-                       internalCheck(obj);
-               }
-               finally
-               {
-                       stack.pop();
-               }
-       }
-
-       private void internalCheck(Object obj)
-       {
-               if (obj == null)
-               {
-                       return;
-               }
-
-               Class<?> cls = obj.getClass();
-               nameStack.add(simpleName);
-               traceStack.add(new TraceSlot(obj, fieldDescription));
-
-               for (IObjectChecker checker : checkers)
-               {
-                       IObjectChecker.Result result = checker.check(obj);
-                       if (result.status == 
IObjectChecker.Result.Status.FAILURE)
-                       {
-                               String prettyPrintMessage = 
toPrettyPrintedStack(Classes.name(cls));
-                               String exceptionMessage = result.reason + '\n' 
+ prettyPrintMessage;
-                               throw new 
ObjectCheckException(exceptionMessage, result.cause);
-                       }
-               }
-
-               ObjectStreamClass desc;
-               for (;;)
-               {
-                       try
-                       {
-                               desc = 
(ObjectStreamClass)LOOKUP_METHOD.invoke(null, cls, Boolean.TRUE);
-                               Class<?> repCl;
-                               if 
(!(Boolean)HAS_WRITE_REPLACE_METHOD_METHOD.invoke(desc, (Object[])null) ||
-                                               (obj = 
INVOKE_WRITE_REPLACE_METHOD.invoke(desc, obj)) == null ||
-                                               (repCl = obj.getClass()) == cls)
-                               {
-                                       break;
-                               }
-                               cls = repCl;
-                       }
-                       catch (IllegalAccessException e)
-                       {
-                               throw new RuntimeException(e);
-                       }
-                       catch (InvocationTargetException e)
-                       {
-                               throw new RuntimeException(e);
-                       }
-               }
-
-               if (cls.isPrimitive())
-               {
-                       // skip
-               }
-               else if (cls.isArray())
-               {
-                       checked.put(obj, null);
-                       Class<?> ccl = cls.getComponentType();
-                       if (!(ccl.isPrimitive()))
-                       {
-                               Object[] objs = (Object[])obj;
-                               for (int i = 0; i < objs.length; i++)
-                               {
-                                       CharSequence arrayPos = new 
StringBuilder(4).append('[').append(i).append(']');
-                                       simpleName = arrayPos;
-                                       fieldDescription += arrayPos;
-                                       check(objs[i]);
-                               }
-                       }
-               }
-               else if (obj instanceof Externalizable && 
(!Proxy.isProxyClass(cls)))
-               {
-                       Externalizable extObj = (Externalizable)obj;
-                       try
-                       {
-                               extObj.writeExternal(new ObjectOutputAdaptor()
-                               {
-                                       private int count = 0;
-
-                                       public void writeObject(Object 
streamObj) throws IOException
-                                       {
-                                               // Check for circular reference.
-                                               if 
(checked.containsKey(streamObj))
-                                               {
-                                                       return;
-                                               }
-
-                                               checked.put(streamObj, null);
-                                               CharSequence arrayPos = new 
StringBuilder(10).append("[write:").append(count++).append(']');
-                                               simpleName = arrayPos;
-                                               fieldDescription += arrayPos;
-
-                                               check(streamObj);
-                                       }
-                               });
-                       }
-                       catch (Exception e)
-                       {
-                               if (e instanceof ObjectCheckException)
-                               {
-                                       throw (ObjectCheckException)e;
-                               }
-                               log.warn("Error delegating to Externalizable : 
{}, path: {}", e.getMessage(), currentPath());
-                       }
-               }
-               else
-               {
-                       Method writeObjectMethod = null;
-                       if (writeObjectMethodMissing.contains(cls) == false)
-                       {
-                               try
-                               {
-                                       writeObjectMethod = 
cls.getDeclaredMethod("writeObject",
-                                                       new Class[] { 
java.io.ObjectOutputStream.class });
-                               }
-                               catch (SecurityException e)
-                               {
-                                       // we can't access / set accessible to 
true
-                                       writeObjectMethodMissing.add(cls);
-                               }
-                               catch (NoSuchMethodException e)
-                               {
-                                       // cls doesn't have that method
-                                       writeObjectMethodMissing.add(cls);
-                               }
-                       }
-
-                       final Object original = obj;
-                       if (writeObjectMethod != null)
-                       {
-                               class InterceptingObjectOutputStream extends 
ObjectOutputStream
-                               {
-                                       private int counter;
-
-                                       InterceptingObjectOutputStream() throws 
IOException
-                                       {
-                                               super(DUMMY_OUTPUT_STREAM);
-                                               enableReplaceObject(true);
-                                       }
-
-                                       @Override
-                                       protected Object replaceObject(Object 
streamObj) throws IOException
-                                       {
-                                               if (streamObj == original)
-                                               {
-                                                       return streamObj;
-                                               }
-
-                                               counter++;
-                                               // Check for circular reference.
-                                               if 
(checked.containsKey(streamObj))
-                                               {
-                                                       return null;
-                                               }
-
-                                               checked.put(streamObj, null);
-                                               CharSequence arrayPos = new 
StringBuilder(10).append("[write:").append(counter).append(']');
-                                               simpleName = arrayPos;
-                                               fieldDescription += arrayPos;
-                                               check(streamObj);
-                                               return streamObj;
-                                       }
-                               }
-                               try
-                               {
-                                       InterceptingObjectOutputStream ioos = 
new InterceptingObjectOutputStream();
-                                       ioos.writeObject(obj);
-                               }
-                               catch (Exception e)
-                               {
-                                       if (e instanceof ObjectCheckException)
-                                       {
-                                               throw (ObjectCheckException)e;
-                                       }
-                                       log.warn("error delegating to 
writeObject : {}, path: {}", e.getMessage(), currentPath());
-                               }
-                       }
-                       else
-                       {
-                               Object[] slots;
-                               try
-                               {
-                                       slots = 
(Object[])GET_CLASS_DATA_LAYOUT_METHOD.invoke(desc, (Object[])null);
-                               }
-                               catch (Exception e)
-                               {
-                                       throw new RuntimeException(e);
-                               }
-                               for (Object slot : slots)
-                               {
-                                       ObjectStreamClass slotDesc;
-                                       try
-                                       {
-                                               Field descField = 
slot.getClass().getDeclaredField("desc");
-                                               descField.setAccessible(true);
-                                               slotDesc = 
(ObjectStreamClass)descField.get(slot);
-                                       }
-                                       catch (Exception e)
-                                       {
-                                               throw new RuntimeException(e);
-                                       }
-                                       checked.put(obj, null);
-                                       checkFields(obj, slotDesc);
-                               }
-                       }
-               }
-
-               traceStack.removeLast();
-               nameStack.removeLast();
-       }
-
-       private void checkFields(Object obj, ObjectStreamClass desc)
-       {
-               int numFields;
-               try
-               {
-                       numFields = 
(Integer)GET_NUM_OBJ_FIELDS_METHOD.invoke(desc, (Object[])null);
-               }
-               catch (IllegalAccessException e)
-               {
-                       throw new RuntimeException(e);
-               }
-               catch (InvocationTargetException e)
-               {
-                       throw new RuntimeException(e);
-               }
-
-               if (numFields > 0)
-               {
-                       int numPrimFields;
-                       ObjectStreamField[] fields = desc.getFields();
-                       Object[] objVals = new Object[numFields];
-                       numPrimFields = fields.length - objVals.length;
-                       try
-                       {
-                               GET_OBJ_FIELD_VALUES_METHOD.invoke(desc, obj, 
objVals);
-                       }
-                       catch (IllegalAccessException e)
-                       {
-                               throw new RuntimeException(e);
-                       }
-                       catch (InvocationTargetException e)
-                       {
-                               throw new RuntimeException(e);
-                       }
-                       for (int i = 0; i < objVals.length; i++)
-                       {
-                               if (objVals[i] instanceof String || objVals[i] 
instanceof Number ||
-                                               objVals[i] instanceof Date || 
objVals[i] instanceof Boolean ||
-                                               objVals[i] instanceof Class)
-                               {
-                                       // filter out common cases
-                                       continue;
-                               }
-
-                               // Check for circular reference.
-                               if (checked.containsKey(objVals[i]))
-                               {
-                                       continue;
-                               }
-
-                               ObjectStreamField fieldDesc = 
fields[numPrimFields + i];
-                               Field field;
-                               try
-                               {
-                                       field = 
(Field)GET_FIELD_METHOD.invoke(fieldDesc, (Object[])null);
-                               }
-                               catch (IllegalAccessException e)
-                               {
-                                       throw new RuntimeException(e);
-                               }
-                               catch (InvocationTargetException e)
-                               {
-                                       throw new RuntimeException(e);
-                               }
-
-                               simpleName = field.getName();
-                               fieldDescription = field.toString();
-                               check(objVals[i]);
-                       }
-               }
-       }
-
-       /**
-        * @return name from root to current node concatenated with slashes
-        */
-       private StringBuilder currentPath()
-       {
-               StringBuilder b = new StringBuilder();
-               for (Iterator<CharSequence> it = nameStack.iterator(); 
it.hasNext();)
-               {
-                       b.append(it.next());
-                       if (it.hasNext())
-                       {
-                               b.append('/');
-                       }
-               }
-               return b;
-       }
-
-       /**
-        * Dump with indentation.
-        *
-        * @param type
-        *            the type that couldn't be serialized
-        * @return A very pretty dump
-        */
-       protected final String toPrettyPrintedStack(String type)
-       {
-               StringBuilder result = new StringBuilder(512);
-               StringBuilder spaces = new StringBuilder(32);
-               result.append("A problem occurred while checking object with 
type: ");
-               result.append(type);
-               result.append("\nField hierarchy is:");
-               for (TraceSlot slot : traceStack)
-               {
-                       spaces.append(' ').append(' ');
-                       
result.append('\n').append(spaces).append(slot.fieldDescription);
-                       result.append(" 
[class=").append(Classes.name(slot.object.getClass()));
-                       if (slot.object instanceof Component)
-                       {
-                               Component component = (Component)slot.object;
-                               result.append(", 
path=").append(component.getPath());
-                       }
-                       result.append(']');
-               }
-               result.append(" <----- field that is causing the problem");
-               return result.toString();
-       }
-
-       /**
-        * @see java.io.ObjectOutputStream#writeObjectOverride(java.lang.Object)
-        */
-       @Override
-       protected final void writeObjectOverride(Object obj) throws IOException
-       {
-               if (!available)
-               {
-                       return;
-               }
-               root = obj;
-               if (fieldDescription == null)
-               {
-                       fieldDescription = (root instanceof Component) ? 
((Component)root).getPath() : "";
-               }
-
-               check(root);
-       }
-
-       /**
-        * @see java.io.ObjectOutputStream#reset()
-        */
-       @Override
-       public void reset() throws IOException
-       {
-               root = null;
-               checked.clear();
-               fieldDescription = null;
-               simpleName = null;
-               traceStack.clear();
-               nameStack.clear();
-               writeObjectMethodMissing.clear();
-       }
-
-       @Override
-       public void close() throws IOException
-       {
-               // do not call super.close() because SerializableChecker uses 
ObjectOutputStream's no-arg constructor
-
-               // just null-ify the declared members
-               reset();
-       }
-
-}

http://git-wip-us.apache.org/repos/asf/wicket/blob/486b7eb8/wicket-core/src/test/java/org/apache/wicket/util/io/SerializableCheckerTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/util/io/SerializableCheckerTest.java
 
b/wicket-core/src/test/java/org/apache/wicket/util/io/SerializableCheckerTest.java
index 3331c8d..d82f820 100644
--- 
a/wicket-core/src/test/java/org/apache/wicket/util/io/SerializableCheckerTest.java
+++ 
b/wicket-core/src/test/java/org/apache/wicket/util/io/SerializableCheckerTest.java
@@ -24,7 +24,7 @@ import org.apache.log4j.Level;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
 import org.apache.wicket.util.Log4jEventHistory;
-import org.apache.wicket.util.objects.checker.ObjectChecker;
+import org.apache.wicket.util.objects.checker.CheckingObjectOutputStream;
 import org.apache.wicket.util.value.ValueMap;
 import org.junit.Assert;
 import org.junit.Test;
@@ -57,7 +57,7 @@ public class SerializableCheckerTest extends Assert
        @Test
        public void runtimeExceptionTolerance() throws IOException
        {
-               Logger logger = LogManager.getLogger(ObjectChecker.class);
+               Logger logger = 
LogManager.getLogger(CheckingObjectOutputStream.class);
                logger.setLevel(Level.WARN);
                Log4jEventHistory logHistory = new Log4jEventHistory();
                logger.addAppender(logHistory);
@@ -88,7 +88,7 @@ public class SerializableCheckerTest extends Assert
                {
                        serializableChecker.writeObject(new TestType2());
                }
-               catch (ObjectChecker.ObjectCheckException e)
+               catch (CheckingObjectOutputStream.ObjectCheckException e)
                {
                        exceptionMessage = e.getMessage();
                }

Reply via email to