Author: jcompagner
Date: Wed Feb 21 14:56:46 2007
New Revision: 510287

URL: http://svn.apache.org/viewvc?view=rev&rev=510287
Log:
better error reporting
first cut of proxy support/writeReplace

Added:
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketSerializeableException.java
   (with props)
Modified:
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/ClassStreamHandler.java
    
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketObjectOutputStream.java

Modified: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/ClassStreamHandler.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/ClassStreamHandler.java?view=diff&rev=510287&r1=510286&r2=510287
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/ClassStreamHandler.java
 (original)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/ClassStreamHandler.java
 Wed Feb 21 14:56:46 2007
@@ -28,6 +28,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import java.security.AccessController;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -137,6 +138,9 @@
        private final short classId;
 
        private final Constructor cons;
+       
+       private final Method writeReplaceMethod;
+       private final Method readResolveMethod;
 
        private final List writeObjectMethods;
 
@@ -145,15 +149,18 @@
 
        private final PrimitiveArray primitiveArray;
 
+
+       private boolean isProxy;
+
        /**
         * Construct.
         * 
         * @param cls
         * @param wicketObjectOutputStream
         *            TODO
-        * @throws NotSerializableException 
+        * @throws WicketSerializeableException 
         */
-       private ClassStreamHandler(Class cls) throws NotSerializableException
+       private ClassStreamHandler(Class cls) throws 
WicketSerializeableException
        {
                this.classId = classCounter++;
                this.clz = cls;
@@ -163,6 +170,10 @@
                        cons = null;
                        writeObjectMethods = null;
                        readObjectMethods = null;
+                       
+                       writeReplaceMethod = null;
+                       readResolveMethod = null;
+                       
                        if (clz == boolean.class)
                        {
                                primitiveArray = new BooleanPrimitiveArray();
@@ -206,21 +217,46 @@
                        cons = null;
                        writeObjectMethods = null;
                        readObjectMethods = null;
+                       writeReplaceMethod = null;
+                       readResolveMethod = null;
+                       primitiveArray = null;
+                       isProxy = false;
+               }
+               else if (Proxy.isProxyClass(clz))
+               {
+                       isProxy = true;
+                       fields = null;
+                       cons = null;
+                       writeObjectMethods = null;
+                       writeReplaceMethod = null;
+                       readResolveMethod = null;
+                       readObjectMethods = null;
                        primitiveArray = null;
                }
                else
                {
-                       this.fields = new ArrayList();
-                       cons = getSerializableConstructor(clz);
-                       if (cons == null)
-                       {
-                               throw new NotSerializableException("No 
serializeable constructor found for " + cls);
-                       }
-                       
-                       writeObjectMethods = new ArrayList();
-                       readObjectMethods = new ArrayList();
+                       fields = new ArrayList();
                        primitiveArray = null;
+               writeObjectMethods = new ArrayList(2);
+                       readObjectMethods = new ArrayList(2);
+                       isProxy = false;
                        
+                   writeReplaceMethod = getInheritableMethod( clz, 
"writeReplace", null, Object.class);
+                   
+                   readResolveMethod = getInheritableMethod(clz, 
"readResolve", null, Object.class);
+                   if (readResolveMethod == null)
+                   {
+                               cons = getSerializableConstructor(clz);
+                               if (cons == null)
+                               {
+                                       throw new 
WicketSerializeableException("No serializeable constructor found for " + cls);
+                               }
+                   }
+                   else
+                   {
+                       cons = null;
+                   }
+
                        Class parent = cls;
                        while(parent != Object.class)
                        {
@@ -231,7 +267,10 @@
                                
                                parent = parent.getSuperclass();
                        }
-                       fillFields(cls);
+                       if (writeReplaceMethod == null)
+                       {
+                               fillFields(cls);
+                       }
                }
        }
 
@@ -331,52 +370,54 @@
         * @param woos
         * @param obj
         * @param out
+        * @throws WicketSerializeableException 
         */
-       public void writeFields(WicketObjectOutputStream woos, Object obj)
+       public void writeFields(WicketObjectOutputStream woos, Object obj) 
throws WicketSerializeableException
        {
+               FieldAndIndex fai = null;
                try
                {
                        for (int i = 0; i < fields.size(); i++)
                        {
-                               FieldAndIndex fai = 
(FieldAndIndex)fields.get(i);
+                               fai = (FieldAndIndex)fields.get(i);
                                fai.writeField(obj, woos);
                        }
                }
-               catch (IllegalArgumentException ex)
+               catch (WicketSerializeableException wse)
                {
-                       throw new RuntimeException(ex);
+                       wse.addTrace(fai.field.getName());
+                       throw wse;
                }
-               catch (IOException ex)
+               catch (Exception ex)
                {
-                       throw new RuntimeException(ex);
+                       throw new WicketSerializeableException("Error writing 
field: " + fai.field.getName() + " for object class: " + obj.getClass(), ex);
                }
 
        }
 
        /**
         * @param wois
+        * @throws WicketSerializeableException 
         */
-       public void readFields(WicketObjectInputStream wois, Object object)
+       public void readFields(WicketObjectInputStream wois, Object object)  
throws WicketSerializeableException
        {
+               FieldAndIndex fai = null;
                try
                {
                        for (int i = 0; i < fields.size(); i++)
                        {
-                               FieldAndIndex fai = 
(FieldAndIndex)fields.get(i);
+                               fai = (FieldAndIndex)fields.get(i);
                                fai.readField(object, wois);
                        }
                }
-               catch (IllegalArgumentException ex)
+               catch (WicketSerializeableException wse)
                {
-                       throw new RuntimeException(ex);
+                       wse.addTrace(fai.field.getName());
+                       throw wse;
                }
-               catch (IOException ex)
+               catch (Exception ex)
                {
-                       throw new RuntimeException(ex);
-               }
-               catch (ClassNotFoundException ex)
-               {
-                       throw new RuntimeException(ex);
+                       throw new WicketSerializeableException("Error reading 
field: " + fai.field.getName() + " for object class: " + object.getClass(),ex);
                }
        }
        
@@ -512,6 +553,55 @@
                        return null;
                }
        }
+       
+       /**
+     * Returns non-static, non-abstract method with given signature provided it
+     * is defined by or accessible (via inheritance) by the given class, or
+     * null if no match found.  Access checks are disabled on the returned
+     * method (if any).
+     */
+    private static Method getInheritableMethod(Class cl, String name,
+                                              Class[] argTypes,
+                                              Class returnType)
+    {
+               Method meth = null;
+               Class defCl = cl;
+               while (defCl != null)
+               {
+                       try
+                       {
+                               meth = defCl.getDeclaredMethod(name, argTypes);
+                               break;
+                       }
+                       catch (NoSuchMethodException ex)
+                       {
+                               defCl = defCl.getSuperclass();
+                       }
+               }
+
+               if ((meth == null) || (meth.getReturnType() != returnType))
+               {
+                       return null;
+               }
+               meth.setAccessible(true);
+               int mods = meth.getModifiers();
+               if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0)
+               {
+                       return null;
+               }
+               else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0)
+               {
+                       return meth;
+               }
+               else if ((mods & Modifier.PRIVATE) != 0)
+               {
+                       return (cl == defCl) ? meth : null;
+               }
+               else
+               {
+                       return packageEquals(cl, defCl) ? meth : null;
+               }
+       }
 
        private static boolean packageEquals(Class cl1, Class cl2)
        {
@@ -1031,6 +1121,26 @@
                        }
                        return array;
                }
+       }
+
+       /**
+        * @return
+        * @throws NotSerializableException 
+        */
+       public Object writeReplace(Object o) throws NotSerializableException
+       {
+               if (writeReplaceMethod != null)
+               {
+                       try
+                       {
+                               return writeReplaceMethod.invoke(o, null);
+                       }
+                       catch (Exception ex)
+                       {
+                               throw new 
NotSerializableException(ex.getMessage());
+                       } 
+               }
+               return null;
        }
        
 }

Modified: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketObjectOutputStream.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketObjectOutputStream.java?view=diff&rev=510287&r1=510286&r2=510287
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketObjectOutputStream.java
 (original)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketObjectOutputStream.java
 Wed Feb 21 14:56:46 2007
@@ -38,7 +38,6 @@
 {
        private wicket.util.collections.HandleTable handledObjects = new 
wicket.util.collections.HandleTable(); 
        
-       private HandleArrayListStack stack = new HandleArrayListStack();
        private HandleArrayListStack defaultWrite = new HandleArrayListStack();
        
        private final DataOutputStream out;
@@ -49,7 +48,7 @@
        private int byteCounter;
 
        private PutField curPut;
-       
+       private Object curObject;
        
        /**
         * Construct.
@@ -89,8 +88,8 @@
                        }
                        else
                        {
-                               handledObjects.assign(obj);
                                Class cls = obj.getClass();
+                               handledObjects.assign(obj);
        
                                if(cls.isArray())
                                {
@@ -98,27 +97,60 @@
                                        ClassStreamHandler classHandler = 
ClassStreamHandler.lookup(componentType);
                                        if(componentType.isPrimitive())
                                        {
-                                               
out.write(ClassStreamHandler.PRIMITIVE_ARRAY);
-                                               
out.writeShort(classHandler.getClassId());
-                                               
classHandler.writeArray(obj,this);
+                                               try
+                                               {
+                                                       
out.write(ClassStreamHandler.PRIMITIVE_ARRAY);
+                                                       
out.writeShort(classHandler.getClassId());
+                                                       
classHandler.writeArray(obj,this);
+                                               }
+                                               catch 
(WicketSerializeableException wse)
+                                               {
+                                                       
wse.addTrace(componentType.getName() + "[" + Array.getLength(obj)+ "]");
+                                                       throw wse;
+                                               }
+                                               catch (Exception e)
+                                               {
+                                                       throw new 
WicketSerializeableException("Error writing primitive array of " + 
componentType.getName()+ "[" + Array.getLength(obj)+ "]",e);
+                                               }
                                        }
                                        else
                                        {
-                                               
out.write(ClassStreamHandler.ARRAY);
-                                               
out.writeShort(classHandler.getClassId());
                                                int length = 
Array.getLength(obj);
-                                               out.writeInt(length);
-                                               for (int i = 0; i < length; i++)
+                                               try
+                                               {
+                                                       
out.write(ClassStreamHandler.ARRAY);
+                                                       
out.writeShort(classHandler.getClassId());
+                                                       out.writeInt(length);
+                                                       for (int i = 0; i < 
length; i++)
+                                                       {
+                                                               
writeObjectOverride(Array.get(obj, i));
+                                                       }
+                                               }
+                                               catch 
(WicketSerializeableException wse)
                                                {
-                                                       
writeObjectOverride(Array.get(obj, i));
+                                                       
wse.addTrace(componentType.getName() + "[" + length+ "]");
+                                                       throw wse;
+                                               }
+                                               catch (Exception e)
+                                               {
+                                                       throw new 
WicketSerializeableException("Error writing array of " + 
componentType.getName()+ "[" + length+ "]",e);
                                                }
                                        }
                                        return;
                                }
                                else
                                {
-                                       classHandler = 
ClassStreamHandler.lookup(cls);
+                                       Class realClz = cls;
+                                       classHandler = 
ClassStreamHandler.lookup(realClz);
                                        
+                                       Object object = 
classHandler.writeReplace(obj);
+                                       if (object != null)
+                                       {
+                                               obj = object;
+                                               realClz = obj.getClass();
+                                               classHandler = 
ClassStreamHandler.lookup(realClz);
+                                       }
+
                                        out.write(ClassStreamHandler.CLASS_DEF);
                                        
out.writeShort(classHandler.getClassId());
                                        // handle strings directly.
@@ -129,14 +161,45 @@
                                        else
                                        {
                                                PutField old = curPut;
+                                               Object oldObject = curObject;
                                                curPut = null;
-                                               stack.push(obj);
-                                               if 
(!classHandler.invokeWriteMethod(this,obj))
+                                               curObject = obj;
+                                               try
+                                               {
+                                                       if 
(!classHandler.invokeWriteMethod(this,obj))
+                                                       {
+                                                               
classHandler.writeFields(this,obj);
+                                                       }
+                                               } 
+                                               catch 
(WicketSerializeableException wse)
+                                               {
+                                                       if (realClz != cls)
+                                                       {
+                                                               
wse.addTrace(realClz.getName() + "(ReplaceOf:" + cls.getName() + ")");
+                                                       }
+                                                       else
+                                                       {
+                                                               
wse.addTrace(realClz.getName());
+                                                       }
+                                                       throw wse;
+                                               }
+                                               catch (Exception e)
+                                               {
+                                                       if (realClz != cls)
+                                                       {
+                                                               throw new 
WicketSerializeableException("Error writing fields for " + realClz.getName()+ 
"(ReplaceOf:" + cls.getName() + ")", e);
+
+                                                       }
+                                                       else
+                                                       {
+                                                               throw new 
WicketSerializeableException("Error writing fields for " + realClz.getName(), 
e);
+                                                       }
+                                               }
+                                               finally
                                                {
-                                                       
classHandler.writeFields(this,obj);
+                                                       curObject = oldObject;
+                                                       curPut = old;
                                                }
-                                               stack.pop();
-                                               curPut = old;
                                        }
                                }
                        }
@@ -148,11 +211,10 @@
         */
        public void defaultWriteObject() throws IOException
        {
-               Object currentObject = stack.peek();
-               if ( !defaultWrite.contains(currentObject))
+               if ( !defaultWrite.contains(curObject))
                {
-                       defaultWrite.add(currentObject);
-                       classHandler.writeFields(this,currentObject);
+                       defaultWrite.add(curObject);
+                       classHandler.writeFields(this,curObject);
                }
        }
        
@@ -304,7 +366,14 @@
     {
        if (curPut == null)
        {
-               curPut = new PutFieldImpl();
+               try
+               {
+                       curPut = new PutFieldImpl();
+               } 
+               catch (Exception e)
+               {
+                       throw new WicketSerializeableException("Error reading 
put fields", e);
+               }
        }
        return curPut;
     }
@@ -316,7 +385,14 @@
     {
        if (curPut != null)
        {
-               curPut.write(this);
+               try
+               {
+                       curPut.write(this);
+               }
+               catch (Exception e)
+               {
+                       throw new WicketSerializeableException("Error writing 
put fields", e);
+               }
        }
     }
        /**
@@ -325,7 +401,8 @@
        public void close() throws IOException
        {
                classHandler = null;
-               stack = null;
+               curObject = null;
+               curPut = null;
                defaultWrite = null;
                out.close();
        }

Added: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketSerializeableException.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketSerializeableException.java?view=auto&rev=510287
==============================================================================
--- 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketSerializeableException.java
 (added)
+++ 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketSerializeableException.java
 Wed Feb 21 14:56:46 2007
@@ -0,0 +1,83 @@
+/*
+ * 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 wicket.util.io;
+
+import java.io.NotSerializableException;
+import java.util.ArrayList;
+import java.util.List;
+
+import wicket.util.string.AppendingStringBuffer;
+
+/**
+ * @author jcompagner
+ */
+public class WicketSerializeableException extends NotSerializableException
+{
+       private static final long serialVersionUID = 1L;
+       
+       private final List list;
+
+       /**
+        * Construct.
+        * @param message 
+        * @param cause 
+        */
+       public WicketSerializeableException(String message)
+       {
+               super(message);
+               list = new ArrayList();
+       }
+       
+       /**
+        * Construct.
+        * @param message 
+        * @param cause 
+        */
+       public WicketSerializeableException(String message, Throwable cause )
+       {
+               this(message);
+               initCause(cause); 
+       }
+
+       /**
+        * @see java.lang.Throwable#getMessage()
+        */
+       public String getMessage()
+       {
+               AppendingStringBuffer asb = new 
AppendingStringBuffer(super.getMessage());
+               if (list.size() > 0)
+               {
+                       asb.append("\n");
+                       for (int i = list.size(); --i >=0 ;)
+                       {
+                               String element = (String)list.get(i);
+                               asb.append(element);
+                               asb.append("->");
+                       }
+                       asb.setLength(asb.length()-2);
+               }
+               return asb.toString();
+       }
+       
+       /**
+        * @param traceString
+        */
+       public void addTrace(String traceString)
+       {
+               list.add(traceString);
+       }
+}

Propchange: 
incubator/wicket/branches/wicket-1.x/wicket/src/main/java/wicket/util/io/WicketSerializeableException.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to