package net.bytebuddy.dynamic.scaffold; import net.bytebuddy.ByteBuddy; import net.bytebuddy.asm.AsmVisitorWrapper; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.field.FieldList; import net.bytebuddy.description.method.MethodList; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.ClassFileLocator; import net.bytebuddy.implementation.Implementation; import net.bytebuddy.pool.TypePool; import net.bytebuddy.test.scope.EnclosingType; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; import java.util.Arrays; import java.util.Collection; @RunWith(Parameterized.class) public class TypeWriterModifierPreservationTest { @Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ // {Object.class}, // {String.class}, // {EnclosingType.class}, // {new EnclosingType().localMethod}, // {new EnclosingType().anonymousMethod}, // {new EnclosingType().localConstructor}, // {new EnclosingType().anonymousConstructor}, // {EnclosingType.LOCAL_INITIALIZER}, {EnclosingType.ANONYMOUS_INITIALIZER}, // {EnclosingType.LOCAL_METHOD}, {EnclosingType.ANONYMOUS_METHOD}, // {EnclosingType.INNER}, // {EnclosingType.NESTED}, // {EnclosingType.PRIVATE_INNER}, // {EnclosingType.PRIVATE_NESTED}, // {EnclosingType.PROTECTED_INNER}, // {EnclosingType.PROTECTED_NESTED}, // {EnclosingType.PACKAGE_INNER}, // {EnclosingType.PACKAGE_NESTED}, // {EnclosingType.FINAL_NESTED}, // {EnclosingType.FINAL_INNER}, // {EnclosingType.DEPRECATED} }); } private final Class<?> type; public TypeWriterModifierPreservationTest(Class<?> type) { this.type = type; } @Test public void testModifiers() throws Exception { TypeModifierExtractor typeModifierExtractor = new TypeModifierExtractor(); new ClassReader(ClassFileLocator.ForClassLoader.read(type).resolve()).accept(typeModifierExtractor, 0); new ByteBuddy() .redefine(type) .visit(new TypeValidator.Wrapper(typeModifierExtractor)) .make(); } private static class TypeModifierExtractor extends ClassVisitor { private String name; public int modifiers, inner; public TypeModifierExtractor() { super(Opcodes.ASM5); } @Override public void visit(int version, int modifiers, String name, String signature, String superName, String[] interfaceName) { this.modifiers = modifiers; this.name = name; } @Override public void visitInnerClass(String name, String outerName, String innerName, int modifiers) { if (name.equals(this.name)) { inner = modifiers; } } } private static class TypeValidator extends ClassVisitor { private String name; public final int modifiers, inner; public TypeValidator(ClassVisitor classVisitor, int modifiers, int inner) { super(Opcodes.ASM5, classVisitor); this.modifiers = modifiers; this.inner = inner; } @Override public void visit(int version, int modifiers, String name, String signature, String superName, String[] interfaceName) { this.name = name; if (modifiers != this.modifiers) { throw new AssertionError("Unexpected modifiers: Observed " + modifiers + " instead of " + this.modifiers); } super.visit(version, modifiers, name, signature, superName, interfaceName); } @Override public void visitInnerClass(String name, String outerName, String innerName, int modifiers) { if (name.equals(this.name) && modifiers != inner) { throw new AssertionError("Unexpected inner modifiers: Observed " + modifiers + " instead of " + inner); } super.visitInnerClass(name, outerName, innerName, modifiers); } private static class Wrapper extends AsmVisitorWrapper.AbstractBase { public final int modifiers, inner; public Wrapper(TypeModifierExtractor typeModifierExtractor) { modifiers = typeModifierExtractor.modifiers; inner = typeModifierExtractor.inner; } @Override public ClassVisitor wrap(TypeDescription instrumentedType, ClassVisitor classVisitor, Implementation.Context implementationContext, TypePool typePool, FieldList<FieldDescription.InDefinedShape> fields, MethodList<?> methods, int writerFlags, int readerFlags) { return new TypeValidator(classVisitor, modifiers, inner); } } } }