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