in xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java [213:296]
private Map<? super Object, ? super Object> createCallbackIndexMap(final Factory source) {
final Callback[] originalCallbacks = source.getCallbacks();
final Callback[] reverseEngineeringCallbacks = new Callback[originalCallbacks.length];
final Map<? super Object, ? super Object> callbackIndexMap = new HashMap<>();
int idxNoOp = -1;
for (int i = 0; i < originalCallbacks.length; i++) {
final Callback callback = originalCallbacks[i];
if (callback == null) {
reverseEngineeringCallbacks[i] = null;
} else if (NoOp.class.isAssignableFrom(callback.getClass())) {
reverseEngineeringCallbacks[i] = NoOp.INSTANCE;
idxNoOp = i;
} else {
reverseEngineeringCallbacks[i] = createReverseEngineeredCallbackOfProperType(callback, i,
callbackIndexMap);
}
}
try {
source.setCallbacks(reverseEngineeringCallbacks);
final Set<Class<?>> interfaces = new HashSet<>();
final Set<Method> methods = new HashSet<>();
Class<?> type = source.getClass();
do {
methods.addAll(Arrays.asList(type.getDeclaredMethods()));
methods.addAll(Arrays.asList(type.getMethods()));
final Class<?>[] implementedInterfaces = type.getInterfaces();
interfaces.addAll(Arrays.asList(implementedInterfaces));
type = type.getSuperclass();
} while (type != null);
for (final Iterator<Class<?>> iterator = interfaces.iterator(); iterator.hasNext();) {
type = iterator.next();
methods.addAll(Arrays.asList(type.getDeclaredMethods()));
}
for (final Iterator<Method> iter = methods.iterator(); iter.hasNext();) {
final Method method = iter.next();
if (!method.isAccessible()) {
method.setAccessible(true);
}
if (Factory.class.isAssignableFrom(method.getDeclaringClass())
|| (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) {
iter.remove();
continue;
}
final Class<?>[] parameterTypes = method.getParameterTypes();
Method calledMethod = method;
try {
if ((method.getModifiers() & Modifier.ABSTRACT) > 0) {
calledMethod = source.getClass().getMethod(method.getName(), method.getParameterTypes());
}
callbackIndexMap.put(null, method);
calledMethod.invoke(source, parameterTypes == null
? (Object[])null
: createNullArguments(parameterTypes));
} catch (final IllegalAccessException e) {
final ObjectAccessException exception = new ObjectAccessException("Cannot access method", e);
exception.add("method", calledMethod.toString());
throw exception;
} catch (final InvocationTargetException e) {
// OK, ignore
} catch (final NoSuchMethodException e) {
final ConversionException exception = new ConversionException(
"CGLIB enhanced proxies wit abstract nethod that has not been implemented");
exception.add("proxy-superclass", type.getSuperclass().getName());
exception.add("method", method.toString());
throw exception;
}
if (callbackIndexMap.containsKey(method)) {
iter.remove();
}
}
if (idxNoOp >= 0) {
final Integer idx = Integer.valueOf(idxNoOp);
for (final Method method : methods) {
callbackIndexMap.put(method, idx);
}
}
} finally {
source.setCallbacks(originalCallbacks);
}
callbackIndexMap.remove(null);
return callbackIndexMap;
}