in xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java [104:178]
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
final Class<?> type = source.getClass();
final boolean hasFactory = Factory.class.isAssignableFrom(type);
writer.startNode("type", type);
context.convertAnother(type.getSuperclass());
writer.endNode();
writer.startNode("interfaces");
final Class<?>[] interfaces = type.getInterfaces();
for (final Class<?> interface1 : interfaces) {
if (interface1 == Factory.class) {
continue;
}
writer.startNode(mapper.serializedClass(interface1.getClass()), interface1.getClass());
context.convertAnother(interface1);
writer.endNode();
}
writer.endNode();
writer.startNode("hasFactory");
writer.setValue(String.valueOf(hasFactory));
writer.endNode();
Map<?, ?> callbackIndexMap = null;
final Callback[] callbacks = hasFactory ? ((Factory)source).getCallbacks() : getCallbacks(source);
if (callbacks.length > 1) {
if (hasFactory) {
callbackIndexMap = createCallbackIndexMap((Factory)source);
} else {
final ConversionException exception = new ConversionException(
"Cannot handle CGLIB enhanced proxies without factory that have multiple callbacks");
exception.add("proxy-superclass", type.getSuperclass().getName());
exception.add("number-of-callbacks", String.valueOf(callbacks.length));
throw exception;
}
writer.startNode("callbacks");
writer.startNode("mapping");
context.convertAnother(callbackIndexMap);
writer.endNode();
}
boolean hasInterceptor = false;
for (final Callback callback : callbacks) {
if (callback == null) {
final String name = mapper.serializedClass(null);
writer.startNode(name);
writer.endNode();
} else {
hasInterceptor = hasInterceptor || MethodInterceptor.class.isAssignableFrom(callback.getClass());
writer.startNode(mapper.serializedClass(callback.getClass()), callback.getClass());
context.convertAnother(callback);
writer.endNode();
}
}
if (callbacks.length > 1) {
writer.endNode();
}
try {
final Field field = type.getDeclaredField("serialVersionUID");
if (!field.isAccessible()) {
field.setAccessible(true);
}
final long serialVersionUID = field.getLong(null);
writer.startNode("serialVersionUID", String.class);
writer.setValue(String.valueOf(serialVersionUID));
writer.endNode();
} catch (final NoSuchFieldException e) {
// OK, ignore
} catch (final IllegalAccessException e) {
final ObjectAccessException exception = new ObjectAccessException("Cannot access field", e);
exception.add("field", type.getName() + ".serialVersionUID");
throw exception;
}
if (hasInterceptor) {
writer.startNode("instance");
super.doMarshalConditionally(source, writer, context);
writer.endNode();
}
}