throws IOException {
final Map<Pair<String, String>, Set<ClassWrapper>> classMap =
new LinkedHashMap<Pair<String, String>, Set<ClassWrapper>>();
for (final Class<?> subtype : subtypes) {
final MutablePair<String, String> key = new MutablePair<String, String>();
final MutableBoolean ignore = new MutableBoolean(false);
final MutableBoolean valid = new MutableBoolean(true);
final MutableBoolean mustRewriteConstructor = new MutableBoolean();
InputStream bytecode = null;
try {
bytecode = env.getClassfile(subtype).getInputStream();
new ClassReader(bytecode).accept(new ClassVisitor(Opcodes.ASM4) {
String superName;
@Override
public void visit(final int version, final int access, final String name, final String signature,
final String superName, final String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
this.superName = superName;
final String left;
if (signature != null) {
left = signature;
} else if (ArrayUtils.getLength(interfaces) == 1) {
left = interfaces[0];
} else {
left = superName;
}
key.setLeft(left);
}
@Override
public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
if (Type.getType(Marker.class).getDescriptor().equals(desc)) {
ignore.setValue(true);
}
return null;
}
@Override
public MethodVisitor visitMethod(final int access, final String name, final String desc,
final String signature, final String[] exceptions) {
if (INIT.equals(name)) {
return new MethodVisitor(Opcodes.ASM4) {
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name,
final String desc) {
if (INIT.equals(name) && owner.equals(superName)) {
key.setRight(desc);
} else {
valid.setValue(false);
}
}
@Override
public void visitFieldInsn(final int opcode, final String owner, final String name,
final String desc) {
if ("this$0".equals(name) && opcode == Opcodes.PUTFIELD) {
mustRewriteConstructor.setValue(true);
return;
}
valid.setValue(false);
}
};
}
return null;
}
}, 0);
} finally {
IOUtils.closeQuietly(bytecode);
}
if (ignore.booleanValue()) {
continue;
}
if (valid.booleanValue()) {
Set<ClassWrapper> set = classMap.get(key);
if (set == null) {
set = new LinkedHashSet<ClassWrapper>();
classMap.put(key, set);
}
set.add(new ClassWrapper(subtype, mustRewriteConstructor.booleanValue()));
} else {
env.debug("%s is ineligible for normalization due to %s", subtype,
IneligibilityReason.TOO_BUSY_CONSTRUCTOR);
}
}