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;
@Override
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);