All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testifyproject.bytebuddy.asm.ModifierAdjustment Maven / Gradle / Ivy

The newest version!
package org.testifyproject.bytebuddy.asm;

import lombok.EqualsAndHashCode;
import org.testifyproject.bytebuddy.description.field.FieldDescription;
import org.testifyproject.bytebuddy.description.field.FieldList;
import org.testifyproject.bytebuddy.description.method.MethodDescription;
import org.testifyproject.bytebuddy.description.method.MethodList;
import org.testifyproject.bytebuddy.description.modifier.ModifierContributor;
import org.testifyproject.bytebuddy.description.type.TypeDescription;
import org.testifyproject.bytebuddy.implementation.Implementation;
import org.testifyproject.bytebuddy.matcher.ElementMatcher;
import org.testifyproject.bytebuddy.pool.TypePool;
import org.testifyproject.bytebuddy.utility.CompoundList;
import org.testifyproject.bytebuddy.jar.asm.ClassVisitor;
import org.testifyproject.bytebuddy.jar.asm.FieldVisitor;
import org.testifyproject.bytebuddy.jar.asm.MethodVisitor;
import org.testifyproject.bytebuddy.jar.asm.Opcodes;

import java.util.*;

import static org.testifyproject.bytebuddy.matcher.ElementMatchers.*;

/**
 * 

* A visitor wrapper that adjusts the modifiers of the instrumented type or its members. *

*

* Important: The removal of the method is not reflected in the created {@link org.testifyproject.bytebuddy.dynamic.DynamicType}'s * type description of the instrumented type. *

* * @see org.testifyproject.bytebuddy.dynamic.Transformer.ForField#withModifiers(ModifierContributor.ForField...) * @see org.testifyproject.bytebuddy.dynamic.Transformer.ForMethod#withModifiers(ModifierContributor.ForMethod...) */ @EqualsAndHashCode(callSuper = false) public class ModifierAdjustment extends AsmVisitorWrapper.AbstractBase { /** * A list of adjustments to apply to the instrumented type. */ private final List> typeAdjustments; /** * A list of adjustments to apply to the instrumented type's declared fields. */ private final List> fieldAdjustments; /** * A list of adjustments to apply to the instrumented type's methods. */ private final List> methodAdjustments; /** * Creates a new modifier adjustment that does not adjust any modifiers. */ public ModifierAdjustment() { this(Collections.>emptyList(), Collections.>emptyList(), Collections.>emptyList()); } /** * Creates a new modifier adjustment. * * @param typeAdjustments A list of adjustments to apply to the instrumented type. * @param fieldAdjustments A list of adjustments to apply to the instrumented type's declared fields. * @param methodAdjustments A list of adjustments to apply to the instrumented type's methods. */ protected ModifierAdjustment(List> typeAdjustments, List> fieldAdjustments, List> methodAdjustments) { this.typeAdjustments = typeAdjustments; this.fieldAdjustments = fieldAdjustments; this.methodAdjustments = methodAdjustments; } /** * Adjusts any instrumented type's modifiers. * * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withTypeModifiers(ModifierContributor.ForType... modifierContributor) { return withTypeModifiers(Arrays.asList(modifierContributor)); } /** * Adjusts any instrumented type's modifiers. * * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withTypeModifiers(List modifierContributors) { return withTypeModifiers(any(), modifierContributors); } /** * Adjusts an instrumented type's modifiers if it matches the supplied matcher. * * @param matcher The matcher that determines a type's eligibility. * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withTypeModifiers(ElementMatcher matcher, ModifierContributor.ForType... modifierContributor) { return withTypeModifiers(matcher, Arrays.asList(modifierContributor)); } /** * Adjusts an instrumented type's modifiers if it matches the supplied matcher. * * @param matcher The matcher that determines a type's eligibility. * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withTypeModifiers(ElementMatcher matcher, List modifierContributors) { return new ModifierAdjustment(CompoundList.of(typeAdjustments, new Adjustment(matcher, ModifierContributor.Resolver.of(modifierContributors))), fieldAdjustments, methodAdjustments); } /** * Adjusts any field's modifiers. * * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withFieldModifiers(ModifierContributor.ForField... modifierContributor) { return withFieldModifiers(Arrays.asList(modifierContributor)); } /** * Adjusts any field's modifiers. * * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withFieldModifiers(List modifierContributors) { return withFieldModifiers(any(), modifierContributors); } /** * Adjusts a field's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a field's modifiers should be adjusted. * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withFieldModifiers(ElementMatcher matcher, ModifierContributor.ForField... modifierContributor) { return withFieldModifiers(matcher, Arrays.asList(modifierContributor)); } /** * Adjusts a field's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a field's modifiers should be adjusted. * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withFieldModifiers(ElementMatcher matcher, List modifierContributors) { return new ModifierAdjustment(typeAdjustments, CompoundList.of(fieldAdjustments, new Adjustment(matcher, ModifierContributor.Resolver.of(modifierContributors))), methodAdjustments); } /** * Adjusts any method's modifiers. * * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withMethodModifiers(ModifierContributor.ForMethod... modifierContributor) { return withMethodModifiers(Arrays.asList(modifierContributor)); } /** * Adjusts any method's modifiers. * * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withMethodModifiers(List modifierContributors) { return withMethodModifiers(any(), modifierContributors); } /** * Adjusts a method's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a method's modifiers should be adjusted. * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withMethodModifiers(ElementMatcher matcher, ModifierContributor.ForMethod... modifierContributor) { return withMethodModifiers(matcher, Arrays.asList(modifierContributor)); } /** * Adjusts a method's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a method's modifiers should be adjusted. * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withMethodModifiers(ElementMatcher matcher, List modifierContributors) { return withInvokableModifiers(isMethod().and(matcher), modifierContributors); } /** * Adjusts any constructor's modifiers. * * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withConstructorModifiers(ModifierContributor.ForMethod... modifierContributor) { return withConstructorModifiers(Arrays.asList(modifierContributor)); } /** * Adjusts any constructor's modifiers. * * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withConstructorModifiers(List modifierContributors) { return withConstructorModifiers(any(), modifierContributors); } /** * Adjusts a constructor's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a constructor's modifiers should be adjusted. * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withConstructorModifiers(ElementMatcher matcher, ModifierContributor.ForMethod... modifierContributor) { return withConstructorModifiers(matcher, Arrays.asList(modifierContributor)); } /** * Adjusts a constructor's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a constructor's modifiers should be adjusted. * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withConstructorModifiers(ElementMatcher matcher, List modifierContributors) { return withInvokableModifiers(isConstructor().and(matcher), modifierContributors); } /** * Adjusts any method's or constructor's modifiers. * * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withInvokableModifiers(ModifierContributor.ForMethod... modifierContributor) { return withInvokableModifiers(Arrays.asList(modifierContributor)); } /** * Adjusts any method's or constructor's modifiers. * * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withInvokableModifiers(List modifierContributors) { return withInvokableModifiers(any(), modifierContributors); } /** * Adjusts a method's or constructor's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a method's or constructor's modifiers should be adjusted. * @param modifierContributor The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withInvokableModifiers(ElementMatcher matcher, ModifierContributor.ForMethod... modifierContributor) { return withInvokableModifiers(matcher, Arrays.asList(modifierContributor)); } /** * Adjusts a method's or constructor's modifiers if it fulfills the supplied matcher. * * @param matcher The matcher that determines if a method's or constructor's modifiers should be adjusted. * @param modifierContributors The modifier contributors to enforce. * @return A new modifier adjustment that enforces the given modifier contributors and any previous adjustments. */ public ModifierAdjustment withInvokableModifiers(ElementMatcher matcher, List modifierContributors) { return new ModifierAdjustment(typeAdjustments, fieldAdjustments, CompoundList.of(methodAdjustments, new Adjustment(matcher, ModifierContributor.Resolver.of(modifierContributors)))); } @Override public ModifierAdjustingClassVisitor wrap(TypeDescription instrumentedType, ClassVisitor classVisitor, Implementation.Context implementationContext, TypePool typePool, FieldList fields, MethodList methods, int writerFlags, int readerFlags) { Map mappedFields = new HashMap(); for (FieldDescription.InDefinedShape fieldDescription : fields) { mappedFields.put(fieldDescription.getInternalName() + fieldDescription.getDescriptor(), fieldDescription); } Map mappedMethods = new HashMap(); for (MethodDescription methodDescription : CompoundList.of(methods, new MethodDescription.Latent.TypeInitializer(instrumentedType))) { mappedMethods.put(methodDescription.getInternalName() + methodDescription.getDescriptor(), methodDescription); } return new ModifierAdjustingClassVisitor(classVisitor, typeAdjustments, fieldAdjustments, methodAdjustments, instrumentedType, mappedFields, mappedMethods); } /** * A description of a conditional adjustment. * * @param The type of the adjusted element's description. */ @EqualsAndHashCode protected static class Adjustment implements ElementMatcher { /** * The matcher to determine an adjustment. */ private final ElementMatcher matcher; /** * The resolver to apply. */ private final ModifierContributor.Resolver resolver; /** * Creates a new adjustment. * * @param matcher The matcher to determine an adjustment. * @param resolver The resolver to apply. */ protected Adjustment(ElementMatcher matcher, ModifierContributor.Resolver resolver) { this.matcher = matcher; this.resolver = resolver; } @Override public boolean matches(T target) { return matcher.matches(target); } /** * Resolves a modifier. * * @param modifiers The original modifiers. * @return The resolved modifiers. */ protected int resolve(int modifiers) { return resolver.resolve(modifiers); } } /** * A class visitor that enforces a collection of modifier adjustments. */ protected static class ModifierAdjustingClassVisitor extends ClassVisitor { /** * A list of type modifier adjustments to apply. */ private final List> typeAdjustments; /** * A list of field modifier adjustments to apply. */ private final List> fieldAdjustments; /** * A list of method modifier adjustments to apply. */ private final List> methodAdjustments; /** * The instrumented type. */ private final TypeDescription instrumentedType; /** * A mapping of field names and descriptors to their description. */ private final Map fields; /** * A mapping of method names and descriptors to their description. */ private final Map methods; /** * Creates a new modifier adjusting visitor. * * @param classVisitor The class visitor to delegate to. * @param typeAdjustments A list of type modifier adjustments to apply. * @param fieldAdjustments A list of field modifier adjustments to apply. * @param methodAdjustments A list of method modifier adjustments to apply. * @param instrumentedType The instrumented type. * @param fields A mapping of field names and descriptors to their description. * @param methods A mapping of method names and descriptors to their description. */ protected ModifierAdjustingClassVisitor(ClassVisitor classVisitor, List> typeAdjustments, List> fieldAdjustments, List> methodAdjustments, TypeDescription instrumentedType, Map fields, Map methods) { super(Opcodes.ASM6, classVisitor); this.typeAdjustments = typeAdjustments; this.fieldAdjustments = fieldAdjustments; this.methodAdjustments = methodAdjustments; this.instrumentedType = instrumentedType; this.fields = fields; this.methods = methods; } @Override public void visit(int version, int modifiers, String internalName, String signature, String superClassName, String[] interfaceName) { for (Adjustment adjustment : typeAdjustments) { if (adjustment.matches(instrumentedType)) { modifiers = adjustment.resolve(modifiers); } } super.visit(version, modifiers, internalName, signature, superClassName, interfaceName); } @Override public void visitInnerClass(String internalName, String outerName, String innerName, int modifiers) { if (instrumentedType.getInternalName().equals(internalName)) { for (Adjustment adjustment : typeAdjustments) { if (adjustment.matches(instrumentedType)) { modifiers = adjustment.resolve(modifiers); } } } super.visitInnerClass(internalName, outerName, innerName, modifiers); } @Override public FieldVisitor visitField(int modifiers, String internalName, String descriptor, String signature, Object value) { FieldDescription.InDefinedShape fieldDescription = fields.get(internalName + descriptor); if (fieldDescription != null) { for (Adjustment adjustment : fieldAdjustments) { if (adjustment.matches(fieldDescription)) { modifiers = adjustment.resolve(modifiers); } } } return super.visitField(modifiers, internalName, descriptor, signature, value); } @Override public MethodVisitor visitMethod(int modifiers, String internalName, String descriptor, String signature, String[] exception) { MethodDescription methodDescription = methods.get(internalName + descriptor); if (methodDescription != null) { for (Adjustment adjustment : methodAdjustments) { if (adjustment.matches(methodDescription)) { modifiers = adjustment.resolve(modifiers); } } } return super.visitMethod(modifiers, internalName, descriptor, signature, exception); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy