Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.bytebuddy.ByteBuddy Maven / Gradle / Ivy
package net.bytebuddy;
import net.bytebuddy.asm.ClassVisitorWrapper;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.BridgeMethodResolver;
import net.bytebuddy.dynamic.scaffold.FieldRegistry;
import net.bytebuddy.dynamic.scaffold.MethodRegistry;
import net.bytebuddy.dynamic.scaffold.inline.InlineDynamicTypeBuilder;
import net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder;
import net.bytebuddy.instrumentation.Instrumentation;
import net.bytebuddy.instrumentation.ModifierContributor;
import net.bytebuddy.instrumentation.attribute.FieldAttributeAppender;
import net.bytebuddy.instrumentation.attribute.MethodAttributeAppender;
import net.bytebuddy.instrumentation.attribute.TypeAttributeAppender;
import net.bytebuddy.instrumentation.method.MethodDescription;
import net.bytebuddy.instrumentation.method.MethodLookupEngine;
import net.bytebuddy.instrumentation.type.TypeDescription;
import net.bytebuddy.instrumentation.type.TypeList;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.modifier.TypeManifestation;
import net.bytebuddy.jar.asm.Opcodes;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static net.bytebuddy.matcher.ElementMatchers.*;
import static net.bytebuddy.utility.ByteBuddyCommons.*;
/**
* {@code ByteBuddy} instances are configurable factories for creating new Java types at a JVM's runtime.
* Such types are represented by {@link net.bytebuddy.dynamic.DynamicType}s which can be saved to disk or loaded into
* the Java virtual machine. Each instance of {@code ByteBuddy} is immutable where any of the factory methods returns
* a new instance that represents the altered configuration.
*
* Note that any configuration defines to ignore the instrumentation of any synthetic methods or the default finalizer
* method {@link Object#finalize()}. This behavior can be altered by
* {@link net.bytebuddy.ByteBuddy#withIgnoredMethods(net.bytebuddy.matcher.ElementMatcher)}.
*/
public class ByteBuddy {
/**
* The default prefix for the default {@link net.bytebuddy.NamingStrategy}.
*/
public static final String BYTE_BUDDY_DEFAULT_PREFIX = "ByteBuddy";
/**
* The class file version of the current configuration.
*/
protected final ClassFileVersion classFileVersion;
/**
* The naming strategy of the current configuration.
*/
protected final NamingStrategy.Unbound namingStrategy;
/**
* A list of interface types to be implemented by any class that is implemented by the current configuration.
*/
protected final List interfaceTypes;
/**
* A matcher for identifying methods that should never be intercepted.
*/
protected final ElementMatcher super MethodDescription> ignoredMethods;
/**
* The factory for generating a bridge method resolver for the current configuration.
*/
protected final BridgeMethodResolver.Factory bridgeMethodResolverFactory;
/**
* The class visitor wrapper chain for the current configuration.
*/
protected final ClassVisitorWrapper.Chain classVisitorWrapperChain;
/**
* The method registry for the current configuration.
*/
protected final MethodRegistry methodRegistry;
/**
* The modifiers to apply to any type that is generated by this configuration.
*/
protected final Definable modifiers;
/**
* The method lookup engine factory to apply to any type that is generated by this configuration.
*/
protected final MethodLookupEngine.Factory methodLookupEngineFactory;
/**
* The type attribute appender factory to apply to any type that is generated by this configuration.
*/
protected final TypeAttributeAppender typeAttributeAppender;
/**
* The default field attribute appender factory which is applied to any field that is defined
* for instrumentations that are applied by this configuration.
*/
protected final FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory;
/**
* The default method attribute appender factory which is applied to any method that is defined
* or intercepted for instrumentations that are applied by this configuration.
*/
protected final MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory;
/**
* Defines a new {@code ByteBuddy} default configuration for the current Java virtual machine's
* class file version.
*/
public ByteBuddy() {
this(ClassFileVersion.forCurrentJavaVersion());
}
/**
* Defines a new {@code ByteBuddy} default configuration for the given class file version.
*
* @param classFileVersion The class file version to apply.
*/
public ByteBuddy(ClassFileVersion classFileVersion) {
this(nonNull(classFileVersion),
new NamingStrategy.Unbound.Default(BYTE_BUDDY_DEFAULT_PREFIX),
new TypeList.Empty(),
isDefaultFinalizer().or(isSynthetic().and(not(isVisibilityBridge()))),
BridgeMethodResolver.Simple.Factory.FAIL_ON_REQUEST,
new ClassVisitorWrapper.Chain(),
new MethodRegistry.Default(),
new Definable.Undefined(),
TypeAttributeAppender.NoOp.INSTANCE,
MethodLookupEngine.Default.Factory.INSTANCE,
FieldAttributeAppender.NoOp.INSTANCE,
MethodAttributeAppender.NoOp.INSTANCE);
}
/**
* Defines a new {@code ByteBuddy} configuration.
*
* @param classFileVersion The currently defined class file version.
* @param namingStrategy The currently defined naming strategy.
* @param interfaceTypes The currently defined collection of interfaces to be implemented
* by any dynamically created type.
* @param ignoredMethods The methods to always be ignored.
* @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation
* process.
* @param classVisitorWrapperChain The class visitor wrapper chain to be applied to any instrumentation
* process.
* @param methodRegistry The currently valid method registry.
* @param modifiers The modifiers to define for any instrumentation process.
* @param typeAttributeAppender The type attribute appender to apply to any instrumentation process.
* @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration.
* @param defaultFieldAttributeAppenderFactory The field attribute appender to apply as a default for any field
* definition.
* @param defaultMethodAttributeAppenderFactory The method attribute appender to apply as a default for any
* method definition or instrumentation.
*/
protected ByteBuddy(ClassFileVersion classFileVersion,
NamingStrategy.Unbound namingStrategy,
List interfaceTypes,
ElementMatcher super MethodDescription> ignoredMethods,
BridgeMethodResolver.Factory bridgeMethodResolverFactory,
ClassVisitorWrapper.Chain classVisitorWrapperChain,
MethodRegistry methodRegistry,
Definable modifiers,
TypeAttributeAppender typeAttributeAppender,
MethodLookupEngine.Factory methodLookupEngineFactory,
FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory,
MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory) {
this.classFileVersion = classFileVersion;
this.namingStrategy = namingStrategy;
this.interfaceTypes = interfaceTypes;
this.ignoredMethods = ignoredMethods;
this.bridgeMethodResolverFactory = bridgeMethodResolverFactory;
this.classVisitorWrapperChain = classVisitorWrapperChain;
this.methodRegistry = methodRegistry;
this.modifiers = modifiers;
this.typeAttributeAppender = typeAttributeAppender;
this.methodLookupEngineFactory = methodLookupEngineFactory;
this.defaultFieldAttributeAppenderFactory = defaultFieldAttributeAppenderFactory;
this.defaultMethodAttributeAppenderFactory = defaultMethodAttributeAppenderFactory;
}
/**
* Returns the class file version that is defined for the current configuration.
*
* @return The class file version that is defined for this configuration.
*/
public ClassFileVersion getClassFileVersion() {
return classFileVersion;
}
/**
* Returns the naming strategy for the current configuration.
*
* @return The naming strategy for the current configuration.
*/
public NamingStrategy.Unbound getNamingStrategy() {
return namingStrategy;
}
/**
* Returns the naming strategy for the current configuration.
*
* @return The naming strategy for the current configuration.
*/
public List getInterfaceTypes() {
return Collections.unmodifiableList(interfaceTypes);
}
/**
* Returns the matcher for the ignored methods for the current configuration.
*
* @return The matcher for the ignored methods for the current configuration.
*/
public ElementMatcher super MethodDescription> getIgnoredMethods() {
return ignoredMethods;
}
/**
* Returns the factory for the bridge method resolver for the current configuration.
*
* @return The factory for the bridge method resolver for the current configuration.
*/
public BridgeMethodResolver.Factory getBridgeMethodResolverFactory() {
return bridgeMethodResolverFactory;
}
/**
* Returns the class visitor wrapper chain for the current configuration.
*
* @return The class visitor wrapper chain for the current configuration.
*/
public ClassVisitorWrapper.Chain getClassVisitorWrapperChain() {
return classVisitorWrapperChain;
}
/**
* Returns the method registry for the current configuration.
*
* @return The method registry for the current configuration.
*/
public MethodRegistry getMethodRegistry() {
return methodRegistry;
}
/**
* Returns the modifiers to apply to any type that is generated by this configuration.
*
* @return The modifiers to apply to any type that is generated by this configuration.
*/
public Definable getModifiers() {
return modifiers;
}
/**
* Returns the method lookup engine factory to apply to any type that is generated by this configuration.
*
* @return The method lookup engine factory to apply to any type that is generated by this configuration.
*/
public MethodLookupEngine.Factory getMethodLookupEngineFactory() {
return methodLookupEngineFactory;
}
/**
* Returns the type attribute appender factory to apply to any type that is generated by this configuration.
*
* @return The type attribute appender factory to apply to any type that is generated by this configuration.
*/
public TypeAttributeAppender getTypeAttributeAppender() {
return typeAttributeAppender;
}
/**
* Returns the default field attribute appender factory which is applied to any field that is defined
* for instrumentations that are applied by this configuration.
*
* @return The default field attribute appender factory which is applied to any field that is defined
* for instrumentations that are applied by this configuration.
*/
public FieldAttributeAppender.Factory getDefaultFieldAttributeAppenderFactory() {
return defaultFieldAttributeAppenderFactory;
}
/**
* Returns the default method attribute appender factory which is applied to any method that is defined
* or intercepted for instrumentations that are applied by this configuration.
*
* @return The default method attribute appender factory which is applied to any method that is defined
* or intercepted for instrumentations that are applied by this configuration.
*/
public MethodAttributeAppender.Factory getDefaultMethodAttributeAppenderFactory() {
return defaultMethodAttributeAppenderFactory;
}
/**
* Creates a dynamic type builder that creates a subclass of a given loaded type where the subclass
* is created by the {@link net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy.Default#IMITATE_SUPER_TYPE}
* strategy.
*
* @param superType The type or interface to be extended or implemented by the dynamic type.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that extends or implements the given loaded type.
*/
public DynamicType.Builder subclass(Class superType) {
return subclass(new TypeDescription.ForLoadedType(nonNull(superType)));
}
/**
* Creates a dynamic type builder that creates a subclass of a given loaded type.
*
* @param superType The type or interface to be extended or implemented by the dynamic type.
* @param constructorStrategy The constructor strategy to apply.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that extends or implements the given loaded type.
*/
public DynamicType.Builder subclass(Class superType, ConstructorStrategy constructorStrategy) {
return subclass(new TypeDescription.ForLoadedType(nonNull(superType)), constructorStrategy);
}
/**
* Creates a dynamic type builder that creates a subclass of a given type description where the subclass
* is created by the {@link net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy.Default#IMITATE_SUPER_TYPE}
* strategy.
*
* @param superType The type or interface to be extended or implemented by the dynamic type.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that extends or implements the given type description.
*/
public DynamicType.Builder subclass(TypeDescription superType) {
return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_TYPE);
}
/**
* Creates a dynamic type builder that creates a subclass of a given type description.
*
* @param superType The type or interface to be extended or implemented by the dynamic type.
* @param constructorStrategy The constructor strategy to apply.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that extends or implements the given type description.
*/
public DynamicType.Builder subclass(TypeDescription superType, ConstructorStrategy constructorStrategy) {
TypeDescription actualSuperType = isExtendable(superType);
List interfaceTypes = this.interfaceTypes;
if (nonNull(superType).isInterface()) {
actualSuperType = new TypeDescription.ForLoadedType(Object.class);
interfaceTypes = join(superType, interfaceTypes);
}
return new SubclassDynamicTypeBuilder(classFileVersion,
nonNull(namingStrategy.subclass(superType)),
actualSuperType,
interfaceTypes,
modifiers.resolve(superType.getModifiers() & ~TypeManifestation.INTERFACE.getMask()),
typeAttributeAppender,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
new FieldRegistry.Default(),
methodRegistry,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory,
nonNull(constructorStrategy));
}
/**
* Creates a dynamic type builder for an interface that extends the given interface.
*
* @param type The interface to extend.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that defines an interface that extends the specified
* interface.
*/
@SuppressWarnings("unchecked")
public DynamicType.Builder makeInterface(Class type) {
return (DynamicType.Builder) makeInterface(new TypeDescription.ForLoadedType(nonNull(type)));
}
/**
* Creates a dynamic type builder for an interface that extends a number of given interfaces.
*
* @param type The interface types to extend.
* @return A dynamic type builder for this configuration that defines an interface that extends the specified
* interfaces.
*/
public DynamicType.Builder> makeInterface(Class>... type) {
return makeInterface(new TypeList.ForLoadedType(nonNull(type)));
}
/**
* Creates a dynamic type builder for an interface that extends a number of given interface.
*
* @param typeDescription The interface type to extend.
* @return A dynamic type builder for this configuration that defines an interface that extends the specified
* interface.
*/
public DynamicType.Builder> makeInterface(TypeDescription typeDescription) {
return makeInterface(Arrays.asList(nonNull(typeDescription)));
}
/**
* Creates a dynamic type builder for an interface that extends a number of given interfaces.
*
* @param typeDescriptions The interface types to extend.
* @return A dynamic type builder for this configuration that defines an interface that extends the specified
* interfaces.
*/
public DynamicType.Builder> makeInterface(List typeDescriptions) {
return new SubclassDynamicTypeBuilder(classFileVersion,
namingStrategy.subclass(new TypeDescription.ForLoadedType(Object.class)),
new TypeDescription.ForLoadedType(Object.class),
join(interfaceTypes, nonNull(typeDescriptions)),
modifiers.resolve(Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC),
typeAttributeAppender,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
new FieldRegistry.Default(),
methodRegistry,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory,
ConstructorStrategy.Default.NO_CONSTRUCTORS);
}
/**
*
* Creates a dynamic type builder for redefining of the given type. The given class must be found on the
* class path or by the class's {@link java.lang.ClassLoader}. Otherwise, the class file to the redefined class
* must be located explicitly by providing a locator by
* {@link net.bytebuddy.ByteBuddy#redefine(Class, net.bytebuddy.dynamic.ClassFileLocator)}.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is redefined several times without providing an updated
* version of the class file.
*
*
* @param levelType The type to redefine.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that redefines the given type description.
*/
public DynamicType.Builder redefine(Class levelType) {
return redefine(levelType, ClassFileLocator.ForClassLoader.of(levelType.getClassLoader()));
}
/**
*
* Creates a dynamic type builder for redefining of the given type.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is redefined several times without providing an updated
* version of the class file.
*
*
* @param levelType The type to redefine.
* @param classFileLocator A locator for finding a class file that represents a type.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that redefines the given type description.
*/
public DynamicType.Builder redefine(Class levelType, ClassFileLocator classFileLocator) {
return redefine(new TypeDescription.ForLoadedType(nonNull(levelType)), classFileLocator);
}
/**
*
* Creates a dynamic type builder for redefining of the given type.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is redefined several times without providing an updated
* version of the class file.
*
*
* @param levelType The type to redefine.
* @param classFileLocator A locator for finding a class file that represents a type.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that redefines the given type description.
*/
public DynamicType.Builder redefine(TypeDescription levelType, ClassFileLocator classFileLocator) {
return new InlineDynamicTypeBuilder(classFileVersion,
nonNull(namingStrategy.redefine(levelType)),
nonNull(levelType),
interfaceTypes,
modifiers.resolve(levelType.getModifiers()),
typeAttributeAppender,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
new FieldRegistry.Default(),
methodRegistry,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory,
nonNull(classFileLocator),
InlineDynamicTypeBuilder.TargetHandler.ForRedefinitionInstrumentation.INSTANCE);
}
/**
*
* Creates a dynamic type by weaving any changes into an already defined level type . The rebased type is
* created by adding methods to the level type where the original method implementations are copied to
* renamed, private methods within the created dynamic type and therefore remain invokable as super method calls.
* The result is a rebased type with subclass semantics. The given class must be found on the class path or
* by the provided class's {@link java.lang.ClassLoader}. Otherwise, the class file to the redefined class
* must be located explicitly by providing a locator by
* {@link net.bytebuddy.ByteBuddy#rebase(Class, net.bytebuddy.dynamic.ClassFileLocator)}.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file.
*
*
* @param levelType The type which is to be rebased.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that creates a rebased version of the given type.
*/
public DynamicType.Builder rebase(Class levelType) {
return rebase(levelType, ClassFileLocator.ForClassLoader.of(levelType.getClassLoader()));
}
/**
*
* Creates a dynamic type by weaving any changes into an already defined level type . The rebased type is
* created by adding methods to the level type where the original method implementations are copied to
* renamed, private methods within the created dynamic type and therefore remain invokable as super method calls.
* The result is a rebased type with subclass semantics.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file.
*
*
* @param levelType The type which is to be rebased.
* @param classFileLocator A locator for finding a class file that represents a type.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that creates a rebased version of the given type.
*/
public DynamicType.Builder rebase(Class levelType, ClassFileLocator classFileLocator) {
return rebase(new TypeDescription.ForLoadedType(nonNull(levelType)), classFileLocator);
}
/**
*
* Creates a dynamic type by weaving any changes into an already defined level type . The rebased type is
* created by adding methods to the level type where the original method implementations are copied to
* renamed, private methods within the created dynamic type and therefore remain invokable as super method calls.
* The result is a rebased type with subclass semantics.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file.
*
*
* @param levelType The type which is to be rebased.
* @param classFileLocator A locator for finding a class file that represents a type.
* @param methodNameTransformer The method name transformer that is used for rebasing methods.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that creates a rebased version of the given type.
*/
public DynamicType.Builder rebase(Class levelType,
ClassFileLocator classFileLocator,
MethodRebaseResolver.MethodNameTransformer methodNameTransformer) {
return rebase(new TypeDescription.ForLoadedType(nonNull(levelType)), classFileLocator, methodNameTransformer);
}
/**
*
* Creates a dynamic type by weaving any changes into an already defined level type . The rebased type is
* created by adding methods to the level type where the original method implementations are copied to
* renamed, private methods within the created dynamic type and therefore remain invokable as super method calls.
* The result is a rebased type with subclass semantics.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file.
*
*
* @param levelType The type which is to be rebased.
* @param classFileLocator A locator for finding a class file that represents a type.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that creates a rebased version of the given type.
*/
public DynamicType.Builder rebase(TypeDescription levelType, ClassFileLocator classFileLocator) {
return rebase(levelType, classFileLocator, new MethodRebaseResolver.MethodNameTransformer.Suffixing());
}
/**
*
* Creates a dynamic type by weaving any changes into an already defined level type . The rebased type is
* created by adding methods to the level type where the original method implementations are copied to
* renamed, private methods within the created dynamic type and therefore remain invokable as super method calls.
* The result is a rebased type with subclass semantics.
*
*
* Note : It is possible to experience unexpected errors in case that the provided {@code levelType} and the
* corresponding class file get out of sync, i.e. a type is rebased several times without updating the class file.
*
*
* @param levelType The type which is to be rebased.
* @param classFileLocator A locator for finding a class file that represents a type.
* @param methodNameTransformer The method name transformer that is used for rebasing methods.
* @param The most specific known type that the created dynamic type represents.
* @return A dynamic type builder for this configuration that creates a rebased version of the given type.
*/
public DynamicType.Builder rebase(TypeDescription levelType,
ClassFileLocator classFileLocator,
MethodRebaseResolver.MethodNameTransformer methodNameTransformer) {
return new InlineDynamicTypeBuilder(classFileVersion,
nonNull(namingStrategy.rebase(levelType)),
levelType,
interfaceTypes,
modifiers.resolve(levelType.getModifiers()),
TypeAttributeAppender.NoOp.INSTANCE,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
new FieldRegistry.Default(),
methodRegistry,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory,
nonNull(classFileLocator),
new InlineDynamicTypeBuilder.TargetHandler.ForRebaseInstrumentation(nonNull(methodNameTransformer)));
}
/**
* Defines a new class file version for this configuration.
*
* @param classFileVersion The class file version to define for this configuration.
* @return A new configuration that represents this configuration with the given class file version.
*/
public ByteBuddy withClassFileVersion(ClassFileVersion classFileVersion) {
return new ByteBuddy(nonNull(classFileVersion),
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new naming strategy for this configuration.
*
* @param namingStrategy The unbound naming strategy to apply to the current configuration.
* @return A new configuration that represents this configuration with the given unbound naming strategy.
*/
public ByteBuddy withNamingStrategy(NamingStrategy.Unbound namingStrategy) {
return new ByteBuddy(classFileVersion,
nonNull(namingStrategy),
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new naming strategy for this configuration.
*
* @param namingStrategy The naming strategy to apply to the current configuration.
* @return A new configuration that represents this configuration with the given naming strategy.
*/
public ByteBuddy withNamingStrategy(NamingStrategy namingStrategy) {
return withNamingStrategy(new NamingStrategy.Unbound.Unified(nonNull(namingStrategy)));
}
/**
* Defines a new modifier contributors for this configuration that replaces the currently defined modifier
* contributes which might currently be implicit.
*
* @param modifierContributor The modifier contributors to define explicitly for this configuration.
* @return A new configuration that represents this configuration with the given modifier contributors.
*/
public ByteBuddy withModifiers(ModifierContributor.ForType... modifierContributor) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
new Definable.Defined(
resolveModifierContributors(TYPE_MODIFIER_MASK, nonNull(modifierContributor))),
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new type attribute appender for this configuration that replaces the currently defined type
* attribute appender.
*
* @param typeAttributeAppender The type attribute appender to define for this configuration.
* @return A new configuration that represents this configuration with the given type attribute appender.
*/
public ByteBuddy withAttribute(TypeAttributeAppender typeAttributeAppender) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
nonNull(typeAttributeAppender),
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new type annotation for this configuration that replaces the currently defined type
* attribute appender.
*
* @param annotation The type annotations to define for this configuration.
* @return A new configuration that represents this configuration with the given annotations as its new
* type attribute appender.
*/
public ByteBuddy withTypeAnnotation(Annotation... annotation) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
new TypeAttributeAppender.ForAnnotation(nonNull(annotation)),
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines all dynamic types that are created by this configuration to implement the given interface.
*
* @param type The interface type to implement.
* @return This configuration where any dynamic type that is created by the resulting configuration will
* implement the given interface.
*/
public OptionalMethodInterception withImplementing(Class>... type) {
TypeDescription[] typeDescription = new TypeDescription[type.length];
int index = 0;
for (Class> aType : type) {
typeDescription[index++] = new TypeDescription.ForLoadedType(aType);
}
return withImplementing(typeDescription);
}
/**
* Defines all dynamic types that are created by this configuration to implement the given interface.
*
* @param type The interface type to implement.
* @return The same configuration where any dynamic type that is created by the resulting configuration will
* implement the given interface.
*/
public OptionalMethodInterception withImplementing(TypeDescription... type) {
return new OptionalMethodInterception(classFileVersion,
namingStrategy,
join(interfaceTypes, isInterface(Arrays.asList(type))),
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory,
isDeclaredBy(anyOf((Object[]) type)));
}
/**
* Defines a new method matcher for methods that are ignored by any dynamic type that is created by this
* configuration which will replace the current configuration. By default, this method matcher is defined
* to ignore instrumenting synthetic methods and the default finalizer method. The only exception from per-default
* overridable synthetic methods are bridge methods which is only implemented by the Java compiler to increase a
* method's visibility.
*
* @param ignoredMethods The methods to always be ignored for any instrumentation.
* @return A new configuration that represents this configuration with the given method matcher defining methods
* that are to be ignored for any instrumentation.
*/
public ByteBuddy withIgnoredMethods(ElementMatcher super MethodDescription> ignoredMethods) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
nonNull(ignoredMethods),
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a bridge method resolver factory to be applied to this configuration. A bridge method resolver is
* responsible for determining the target method that is invoked by a bridge method. This way, a super method
* invocation is resolved by invoking the actual super method instead of the bridge method which would in turn
* resolve the actual method virtually.
*
* @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation
* process.
* @return A new configuration that represents this configuration with the given bridge method resolver factory
* to be applied on any configuration.
*/
public ByteBuddy withBridgeMethodResolver(BridgeMethodResolver.Factory bridgeMethodResolverFactory) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
nonNull(bridgeMethodResolverFactory),
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new class visitor to be appended to the current collection of {@link net.bytebuddy.jar.asm.ClassVisitor}s
* that are to be applied onto any creation process of a dynamic type.
*
* @param classVisitorWrapper The class visitor wrapper to ba appended to the current chain of class visitor wrappers.
* @return The same configuration with the given class visitor wrapper to be applied onto any creation process of a dynamic
* type.
*/
public ByteBuddy withClassVisitor(ClassVisitorWrapper classVisitorWrapper) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain.append(nonNull(classVisitorWrapper)),
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new {@link net.bytebuddy.instrumentation.method.MethodLookupEngine.Factory} to be used for creating
* {@link net.bytebuddy.instrumentation.method.MethodLookupEngine}s for type creations based on this configuration.
* The default lookup engine queries any class or interface type that is represented by the created type. These
* queries might however be costly such that this factory can be configured to save lookup time, for example
* by providing additional caching or by providing precomputed results.
*
* @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration.
* @return The same configuration with the method lookup engine factory.
*/
public ByteBuddy withMethodLookupEngine(MethodLookupEngine.Factory methodLookupEngineFactory) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
nonNull(methodLookupEngineFactory),
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new default field attribute appender factory that is applied onto any field.
*
* @param attributeAppenderFactory The attribute appender factory that is applied as a default on any
* field that is created by a dynamic type that is created with this
* configuration.
* @return The same configuration with the given field attribute appender factory to be applied as a default to
* the creation process of any field of a dynamic type.
*/
public ByteBuddy withDefaultFieldAttributeAppender(FieldAttributeAppender.Factory attributeAppenderFactory) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
nonNull(attributeAppenderFactory),
defaultMethodAttributeAppenderFactory);
}
/**
* Defines a new default method attribute appender factory that is applied onto any method.
*
* @param attributeAppenderFactory The attribute appender factory that is applied as a default on any
* method that is created or intercepted by a dynamic type that is created
* with this configuration.
* @return The same configuration with the given method attribute appender factory to be applied as a default to
* the creation or interception process of any method of a dynamic type.
*/
public ByteBuddy withDefaultMethodAttributeAppender(MethodAttributeAppender.Factory attributeAppenderFactory) {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
nonNull(attributeAppenderFactory));
}
/**
* Intercepts a given selection of byte code methods that can be a method or a constructor.
*
* @param methodMatcher The method matcher representing all byte code methods to intercept.
* @return A matched method interception for the given selection.
*/
public MatchedMethodInterception invokable(ElementMatcher super MethodDescription> methodMatcher) {
return new MatchedMethodInterception(nonNull(methodMatcher));
}
/**
* Intercepts a given method selection.
*
* @param methodMatcher The method matcher representing all methods to intercept.
* @return A matched method interception for the given selection.
*/
public MatchedMethodInterception method(ElementMatcher super MethodDescription> methodMatcher) {
return invokable(isMethod().and(nonNull(methodMatcher)));
}
/**
* Intercepts a given constructor selection.
*
* @param methodMatcher The method matcher representing all constructors to intercept.
* @return A matched method interception for the given selection.
*/
public MatchedMethodInterception constructor(ElementMatcher super MethodDescription> methodMatcher) {
return invokable(isConstructor().and(nonNull(methodMatcher)));
}
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || getClass() != other.getClass())
return false;
ByteBuddy byteBuddy = (ByteBuddy) other;
return bridgeMethodResolverFactory.equals(byteBuddy.bridgeMethodResolverFactory)
&& classFileVersion.equals(byteBuddy.classFileVersion)
&& classVisitorWrapperChain.equals(byteBuddy.classVisitorWrapperChain)
&& defaultFieldAttributeAppenderFactory.equals(byteBuddy.defaultFieldAttributeAppenderFactory)
&& defaultMethodAttributeAppenderFactory.equals(byteBuddy.defaultMethodAttributeAppenderFactory)
&& ignoredMethods.equals(byteBuddy.ignoredMethods)
&& interfaceTypes.equals(byteBuddy.interfaceTypes)
&& methodLookupEngineFactory.equals(byteBuddy.methodLookupEngineFactory)
&& methodRegistry.equals(byteBuddy.methodRegistry)
&& modifiers.equals(byteBuddy.modifiers)
&& namingStrategy.equals(byteBuddy.namingStrategy)
&& typeAttributeAppender.equals(byteBuddy.typeAttributeAppender);
}
@Override
public int hashCode() {
int result = classFileVersion.hashCode();
result = 31 * result + namingStrategy.hashCode();
result = 31 * result + interfaceTypes.hashCode();
result = 31 * result + ignoredMethods.hashCode();
result = 31 * result + bridgeMethodResolverFactory.hashCode();
result = 31 * result + classVisitorWrapperChain.hashCode();
result = 31 * result + methodRegistry.hashCode();
result = 31 * result + modifiers.hashCode();
result = 31 * result + methodLookupEngineFactory.hashCode();
result = 31 * result + typeAttributeAppender.hashCode();
result = 31 * result + defaultFieldAttributeAppenderFactory.hashCode();
result = 31 * result + defaultMethodAttributeAppenderFactory.hashCode();
return result;
}
@Override
public String toString() {
return "ByteBuddy{" +
"classFileVersion=" + classFileVersion +
", namingStrategy=" + namingStrategy +
", interfaceTypes=" + interfaceTypes +
", ignoredMethods=" + ignoredMethods +
", bridgeMethodResolverFactory=" + bridgeMethodResolverFactory +
", classVisitorWrapperChain=" + classVisitorWrapperChain +
", methodRegistry=" + methodRegistry +
", modifiers=" + modifiers +
", methodLookupEngineFactory=" + methodLookupEngineFactory +
", typeAttributeAppender=" + typeAttributeAppender +
", defaultFieldAttributeAppenderFactory=" + defaultFieldAttributeAppenderFactory +
", defaultMethodAttributeAppenderFactory=" + defaultMethodAttributeAppenderFactory +
'}';
}
/**
* Any definable instance is either {@link net.bytebuddy.ByteBuddy.Definable.Defined} when a value is provided
* or {@link net.bytebuddy.ByteBuddy.Definable.Undefined} if a value is not provided. A defined definable will
* return its defined value on request while an undefined definable will return the provided default.
*
* @param The type of the definable object.
*/
protected static interface Definable {
/**
* Returns the value of this instance or the provided default value for an undefined definable.
*
* @param defaultValue The default value that is returned for an {@link net.bytebuddy.ByteBuddy.Definable.Undefined}
* definable.
* @return The value that is represented by this instance.
*/
T resolve(T defaultValue);
/**
* Checks if this value is explicitly defined.
*
* @return {@code true} if this value is defined.
*/
boolean isDefined();
/**
* A representation of an undefined {@link net.bytebuddy.ByteBuddy.Definable}.
*
* @param The type of the definable object.
*/
static class Undefined implements Definable {
@Override
public T resolve(T defaultValue) {
return defaultValue;
}
@Override
public boolean isDefined() {
return false;
}
@Override
public boolean equals(Object other) {
return other != null && other.getClass() == Undefined.class;
}
@Override
public int hashCode() {
return 31;
}
@Override
public String toString() {
return "ByteBuddy.Definable.Undefined{}";
}
}
/**
* A representation of a defined {@link net.bytebuddy.ByteBuddy.Definable} for a given value.
*
* @param The type of the definable object.
*/
static class Defined implements Definable {
/**
* The value that is represented by this defined definable.
*/
private final T value;
/**
* Creates a new defined instance for the given value.
*
* @param value The defined value.
*/
public Defined(T value) {
this.value = value;
}
@Override
public T resolve(T defaultValue) {
return value;
}
@Override
public boolean isDefined() {
return true;
}
@Override
public boolean equals(Object o) {
return this == o || !(o == null || getClass() != o.getClass())
&& value.equals(((Defined) o).value);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public String toString() {
return "ByteBuddy.Definable.Defined{value=" + value + '}';
}
}
}
/**
* Implementations of this interface are capable of defining a method interception for a given set of methods.
*/
public static interface MethodInterceptable {
/**
* Intercepts the given method with the given instrumentation.
*
* @param instrumentation The instrumentation to apply to the selected methods.
* @return A method annotation target for this instance with the given instrumentation applied to the
* current selection.
*/
MethodAnnotationTarget intercept(Instrumentation instrumentation);
/**
* Defines the currently selected methods as {@code abstract}.
*
* @return A method annotation target for this instance with implementing the currently selected methods
* as {@code abstract}.
*/
MethodAnnotationTarget withoutCode();
}
/**
* A {@link net.bytebuddy.ByteBuddy} configuration with a selected set of methods for which annotations can
* be defined.
*/
public static class MethodAnnotationTarget extends Proxy {
/**
* The method matcher representing the current method selection.
*/
protected final ElementMatcher super MethodDescription> methodMatcher;
/**
* The instrumentation that was defined for the current method selection.
*/
protected final Instrumentation instrumentation;
/**
* The method attribute appender factory that was defined for the current method selection.
*/
protected final MethodAttributeAppender.Factory attributeAppenderFactory;
/**
* Creates a new method annotation target.
*
* @param classFileVersion The currently defined class file version.
* @param namingStrategy The currently defined naming strategy.
* @param interfaceTypes The currently defined collection of interfaces to be implemented
* by any dynamically created type.
* @param ignoredMethods The methods to always be ignored.
* @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation
* process.
* @param classVisitorWrapperChain The class visitor wrapper chain to be applied to any instrumentation
* process.
* @param methodRegistry The currently valid method registry.
* @param modifiers The modifiers to define for any instrumentation process.
* @param typeAttributeAppender The type attribute appender to apply to any instrumentation process.
* @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration.
* @param defaultFieldAttributeAppenderFactory The field attribute appender to apply as a default for any field
* definition.
* @param defaultMethodAttributeAppenderFactory The method attribute appender to apply as a default for any
* method definition or instrumentation.
* @param methodMatcher The method matcher representing the current method selection.
* @param instrumentation The instrumentation that was defined for the current method
* selection.
* @param attributeAppenderFactory The method attribute appender factory that was defined for the
* current method selection.
*/
protected MethodAnnotationTarget(ClassFileVersion classFileVersion,
NamingStrategy.Unbound namingStrategy,
List interfaceTypes,
ElementMatcher super MethodDescription> ignoredMethods,
BridgeMethodResolver.Factory bridgeMethodResolverFactory,
ClassVisitorWrapper.Chain classVisitorWrapperChain,
MethodRegistry methodRegistry,
Definable modifiers,
TypeAttributeAppender typeAttributeAppender,
MethodLookupEngine.Factory methodLookupEngineFactory,
FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory,
MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory,
ElementMatcher super MethodDescription> methodMatcher,
Instrumentation instrumentation,
MethodAttributeAppender.Factory attributeAppenderFactory) {
super(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
this.methodMatcher = methodMatcher;
this.instrumentation = instrumentation;
this.attributeAppenderFactory = attributeAppenderFactory;
}
/**
* Defines a given attribute appender factory to be applied for the currently selected methods.
*
* @param attributeAppenderFactory The method attribute appender factory to apply to the currently
* selected methods.
* @return A method annotation target that represents the current configuration with the additional
* attribute appender factory applied to the current method selection.
*/
public MethodAnnotationTarget attribute(MethodAttributeAppender.Factory attributeAppenderFactory) {
return new MethodAnnotationTarget(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory,
methodMatcher,
instrumentation,
new MethodAttributeAppender.Factory.Compound(this.attributeAppenderFactory,
nonNull(attributeAppenderFactory)));
}
/**
* Defines an method annotation for the currently selected methods.
*
* @param annotation The annotations to defined for the currently selected methods.
* @return A method annotation target that represents the current configuration with the additional
* annotations added to the currently selected methods.
*/
public MethodAnnotationTarget annotateMethod(Annotation... annotation) {
return attribute(new MethodAttributeAppender.ForAnnotation(nonNull(annotation)));
}
/**
* Defines an method annotation for a parameter of the currently selected methods.
*
* @param parameterIndex The index of the parameter for which the annotations should be applied
* with the first parameter index by {@code 0}.
* @param annotation The annotations to defined for the currently selected methods' parameters
* ath the given index.
* @return A method annotation target that represents the current configuration with the additional
* annotations added to the currently selected methods' parameters at the given index.
*/
public MethodAnnotationTarget annotateParameter(int parameterIndex, Annotation... annotation) {
return attribute(new MethodAttributeAppender.ForAnnotation(parameterIndex, nonNull(annotation)));
}
@Override
protected ByteBuddy materialize() {
return new ByteBuddy(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry.prepend(new MethodRegistry.LatentMethodMatcher.Simple(methodMatcher),
instrumentation,
attributeAppenderFactory),
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory
);
}
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || getClass() != other.getClass())
return false;
if (!super.equals(other))
return false;
MethodAnnotationTarget that = (MethodAnnotationTarget) other;
return attributeAppenderFactory.equals(that.attributeAppenderFactory)
&& instrumentation.equals(that.instrumentation)
&& methodMatcher.equals(that.methodMatcher);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + methodMatcher.hashCode();
result = 31 * result + instrumentation.hashCode();
result = 31 * result + attributeAppenderFactory.hashCode();
return result;
}
@Override
public String toString() {
return "ByteBuddy.MethodAnnotationTarget{" +
"base=" + super.toString() +
", methodMatcher=" + methodMatcher +
", instrumentation=" + instrumentation +
", attributeAppenderFactory=" + attributeAppenderFactory +
'}';
}
}
/**
* An optional method interception that allows to intercept a method selection only if this is needed.
*/
public static class OptionalMethodInterception extends ByteBuddy implements MethodInterceptable {
/**
* The method matcher that defines the selected that is represented by this instance.
*/
protected final ElementMatcher super MethodDescription> methodMatcher;
/**
* Creates a new optional method interception.
*
* @param classFileVersion The currently defined class file version.
* @param namingStrategy The currently defined naming strategy.
* @param interfaceTypes The currently defined collection of interfaces to be implemented
* by any dynamically created type.
* @param ignoredMethods The methods to always be ignored.
* @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any instrumentation
* process.
* @param classVisitorWrapperChain The class visitor wrapper chain to be applied to any instrumentation
* process.
* @param methodRegistry The currently valid method registry.
* @param modifiers The modifiers to define for any instrumentation process.
* @param typeAttributeAppender The type attribute appender to apply to any instrumentation process.
* @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration.
* @param defaultFieldAttributeAppenderFactory The field attribute appender to apply as a default for any field
* definition.
* @param defaultMethodAttributeAppenderFactory The method attribute appender to apply as a default for any
* method definition or instrumentation.
* @param methodMatcher The method matcher representing the current method selection.
*/
protected OptionalMethodInterception(ClassFileVersion classFileVersion,
NamingStrategy.Unbound namingStrategy,
List interfaceTypes,
ElementMatcher super MethodDescription> ignoredMethods,
BridgeMethodResolver.Factory bridgeMethodResolverFactory,
ClassVisitorWrapper.Chain classVisitorWrapperChain,
MethodRegistry methodRegistry,
Definable modifiers,
TypeAttributeAppender typeAttributeAppender,
MethodLookupEngine.Factory methodLookupEngineFactory,
FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory,
MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory,
ElementMatcher super MethodDescription> methodMatcher) {
super(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
this.methodMatcher = methodMatcher;
}
@Override
public MethodAnnotationTarget intercept(Instrumentation instrumentation) {
return new MatchedMethodInterception(methodMatcher).intercept(instrumentation);
}
@Override
public MethodAnnotationTarget withoutCode() {
return new MatchedMethodInterception(methodMatcher).withoutCode();
}
@Override
public boolean equals(Object other) {
return this == other || !(other == null || getClass() != other.getClass()) && super.equals(other)
&& methodMatcher.equals(((OptionalMethodInterception) other).methodMatcher);
}
@Override
public int hashCode() {
return 31 * methodMatcher.hashCode() + super.hashCode();
}
@Override
public String toString() {
return "ByteBuddy.OptionalMethodInterception{" +
"classFileVersion=" + classFileVersion +
", namingStrategy=" + namingStrategy +
", interfaceTypes=" + interfaceTypes +
", ignoredMethods=" + ignoredMethods +
", bridgeMethodResolverFactory=" + bridgeMethodResolverFactory +
", classVisitorWrapperChain=" + classVisitorWrapperChain +
", methodRegistry=" + methodRegistry +
", modifiers=" + modifiers +
", methodLookupEngineFactory=" + methodLookupEngineFactory +
", typeAttributeAppender=" + typeAttributeAppender +
", defaultFieldAttributeAppenderFactory=" + defaultFieldAttributeAppenderFactory +
", defaultMethodAttributeAppenderFactory=" + defaultMethodAttributeAppenderFactory +
", methodMatcher=" + methodMatcher +
'}';
}
}
/**
* A proxy implementation for extending Byte Buddy while allowing for enhancing a {@link net.bytebuddy.ByteBuddy}
* configuration.
*/
protected abstract static class Proxy extends ByteBuddy {
/**
* Defines a new proxy configuration for {@code ByteBuddy}.
*
* @param classFileVersion The currently defined class file version.
* @param namingStrategy The currently defined naming strategy.
* @param interfaceTypes The currently defined collection of interfaces to be
* implemented by any dynamically created type.
* @param ignoredMethods The methods to always be ignored.
* @param bridgeMethodResolverFactory The bridge method resolver factory to be applied to any
* instrumentation process.
* @param classVisitorWrapperChain The class visitor wrapper chain to be applied to any
* instrumentation process.
* @param methodRegistry The currently valid method registry.
* @param modifiers The modifiers to define for any instrumentation process.
* @param typeAttributeAppender The type attribute appender to apply to any instrumentation
* process.
* @param methodLookupEngineFactory The method lookup engine factory to apply to this configuration.
* @param defaultFieldAttributeAppenderFactory The field attribute appender to apply as a default for any
* field definition.
* @param defaultMethodAttributeAppenderFactory The method attribute appender to apply as a default for any
* method definition or instrumentation.
*/
protected Proxy(ClassFileVersion classFileVersion,
NamingStrategy.Unbound namingStrategy,
List interfaceTypes,
ElementMatcher super MethodDescription> ignoredMethods,
BridgeMethodResolver.Factory bridgeMethodResolverFactory,
ClassVisitorWrapper.Chain classVisitorWrapperChain,
MethodRegistry methodRegistry,
Definable modifiers,
TypeAttributeAppender typeAttributeAppender,
MethodLookupEngine.Factory methodLookupEngineFactory,
FieldAttributeAppender.Factory defaultFieldAttributeAppenderFactory,
MethodAttributeAppender.Factory defaultMethodAttributeAppenderFactory) {
super(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory);
}
@Override
public ClassFileVersion getClassFileVersion() {
return materialize().getClassFileVersion();
}
@Override
public NamingStrategy.Unbound getNamingStrategy() {
return materialize().getNamingStrategy();
}
@Override
public List getInterfaceTypes() {
return materialize().getInterfaceTypes();
}
@Override
public ElementMatcher super MethodDescription> getIgnoredMethods() {
return materialize().getIgnoredMethods();
}
@Override
public BridgeMethodResolver.Factory getBridgeMethodResolverFactory() {
return materialize().getBridgeMethodResolverFactory();
}
@Override
public ClassVisitorWrapper.Chain getClassVisitorWrapperChain() {
return materialize().getClassVisitorWrapperChain();
}
@Override
public MethodRegistry getMethodRegistry() {
return materialize().getMethodRegistry();
}
@Override
public Definable getModifiers() {
return materialize().getModifiers();
}
@Override
public MethodLookupEngine.Factory getMethodLookupEngineFactory() {
return materialize().getMethodLookupEngineFactory();
}
@Override
public TypeAttributeAppender getTypeAttributeAppender() {
return materialize().getTypeAttributeAppender();
}
@Override
public FieldAttributeAppender.Factory getDefaultFieldAttributeAppenderFactory() {
return materialize().getDefaultFieldAttributeAppenderFactory();
}
@Override
public MethodAttributeAppender.Factory getDefaultMethodAttributeAppenderFactory() {
return materialize().getDefaultMethodAttributeAppenderFactory();
}
@Override
public DynamicType.Builder subclass(Class superType) {
return materialize().subclass(superType);
}
@Override
public DynamicType.Builder subclass(Class superType, ConstructorStrategy constructorStrategy) {
return materialize().subclass(superType, constructorStrategy);
}
@Override
public DynamicType.Builder subclass(TypeDescription superType) {
return materialize().subclass(superType);
}
@Override
public DynamicType.Builder subclass(TypeDescription superType,
ConstructorStrategy constructorStrategy) {
return materialize().subclass(superType, constructorStrategy);
}
@Override
public DynamicType.Builder redefine(Class levelType) {
return materialize().redefine(levelType);
}
@Override
public DynamicType.Builder redefine(Class levelType,
ClassFileLocator classFileLocator) {
return materialize().redefine(levelType, classFileLocator);
}
@Override
public DynamicType.Builder redefine(TypeDescription levelType,
ClassFileLocator classFileLocator) {
return materialize().redefine(levelType, classFileLocator);
}
@Override
public DynamicType.Builder rebase(Class levelType) {
return materialize().rebase(levelType);
}
@Override
public DynamicType.Builder rebase(Class levelType,
ClassFileLocator classFileLocator) {
return materialize().rebase(levelType, classFileLocator);
}
@Override
public DynamicType.Builder rebase(Class levelType,
ClassFileLocator classFileLocator,
MethodRebaseResolver.MethodNameTransformer methodNameTransformer) {
return materialize().rebase(levelType, classFileLocator, methodNameTransformer);
}
@Override
public DynamicType.Builder rebase(TypeDescription levelType,
ClassFileLocator classFileLocator) {
return materialize().rebase(levelType, classFileLocator);
}
@Override
public DynamicType.Builder rebase(TypeDescription levelType,
ClassFileLocator classFileLocator,
MethodRebaseResolver.MethodNameTransformer methodNameTransformer) {
return super.rebase(levelType, classFileLocator, methodNameTransformer);
}
@Override
public ByteBuddy withClassFileVersion(ClassFileVersion classFileVersion) {
return materialize().withClassFileVersion(classFileVersion);
}
@Override
public ByteBuddy withNamingStrategy(NamingStrategy.Unbound namingStrategy) {
return materialize().withNamingStrategy(namingStrategy);
}
@Override
public ByteBuddy withNamingStrategy(NamingStrategy namingStrategy) {
return materialize().withNamingStrategy(namingStrategy);
}
@Override
public ByteBuddy withModifiers(ModifierContributor.ForType... modifierContributor) {
return materialize().withModifiers(modifierContributor);
}
@Override
public ByteBuddy withAttribute(TypeAttributeAppender typeAttributeAppender) {
return materialize().withAttribute(typeAttributeAppender);
}
@Override
public ByteBuddy withTypeAnnotation(Annotation... annotation) {
return materialize().withTypeAnnotation(annotation);
}
@Override
public OptionalMethodInterception withImplementing(Class>... type) {
return materialize().withImplementing(type);
}
@Override
public OptionalMethodInterception withImplementing(TypeDescription... type) {
return materialize().withImplementing(type);
}
@Override
public ByteBuddy withIgnoredMethods(ElementMatcher super MethodDescription> ignoredMethods) {
return materialize().withIgnoredMethods(ignoredMethods);
}
@Override
public ByteBuddy withBridgeMethodResolver(BridgeMethodResolver.Factory bridgeMethodResolverFactory) {
return materialize().withBridgeMethodResolver(bridgeMethodResolverFactory);
}
@Override
public ByteBuddy withClassVisitor(ClassVisitorWrapper classVisitorWrapper) {
return materialize().withClassVisitor(classVisitorWrapper);
}
@Override
public ByteBuddy withMethodLookupEngine(MethodLookupEngine.Factory methodLookupEngineFactory) {
return materialize().withMethodLookupEngine(methodLookupEngineFactory);
}
@Override
public ByteBuddy withDefaultFieldAttributeAppender(FieldAttributeAppender.Factory attributeAppenderFactory) {
return materialize().withDefaultFieldAttributeAppender(attributeAppenderFactory);
}
@Override
public ByteBuddy withDefaultMethodAttributeAppender(MethodAttributeAppender.Factory attributeAppenderFactory) {
return materialize().withDefaultMethodAttributeAppender(attributeAppenderFactory);
}
@Override
public MatchedMethodInterception invokable(ElementMatcher super MethodDescription> methodMatcher) {
return materialize().invokable(methodMatcher);
}
@Override
public MatchedMethodInterception method(ElementMatcher super MethodDescription> methodMatcher) {
return materialize().method(methodMatcher);
}
@Override
public MatchedMethodInterception constructor(ElementMatcher super MethodDescription> methodMatcher) {
return materialize().constructor(methodMatcher);
}
/**
* Materializes the current extended configuration.
*
* @return The materialized Byte Buddy configuration.
*/
protected abstract ByteBuddy materialize();
}
/**
* A matched method interception for a non-optional method definition.
*/
public class MatchedMethodInterception implements MethodInterceptable {
/**
* A method matcher that represents the current method selection.
*/
protected final ElementMatcher super MethodDescription> methodMatcher;
/**
* Creates a new matched method interception.
*
* @param methodMatcher The method matcher representing the current method selection.
*/
protected MatchedMethodInterception(ElementMatcher super MethodDescription> methodMatcher) {
this.methodMatcher = methodMatcher;
}
@Override
public MethodAnnotationTarget intercept(Instrumentation instrumentation) {
return new MethodAnnotationTarget(classFileVersion,
namingStrategy,
interfaceTypes,
ignoredMethods,
bridgeMethodResolverFactory,
classVisitorWrapperChain,
methodRegistry,
modifiers,
typeAttributeAppender,
methodLookupEngineFactory,
defaultFieldAttributeAppenderFactory,
defaultMethodAttributeAppenderFactory,
methodMatcher,
nonNull(instrumentation),
MethodAttributeAppender.NoOp.INSTANCE);
}
@Override
public MethodAnnotationTarget withoutCode() {
return intercept(Instrumentation.ForAbstractMethod.INSTANCE);
}
/**
* Returns the outer class instance of this instance.
*
* @return The outer class instance.
*/
private ByteBuddy getByteBuddy() {
return ByteBuddy.this;
}
@Override
public boolean equals(Object other) {
return this == other || !(other == null || getClass() != other.getClass())
&& ByteBuddy.this.equals(((MatchedMethodInterception) other).getByteBuddy())
&& methodMatcher.equals(((MatchedMethodInterception) other).methodMatcher);
}
@Override
public int hashCode() {
return 31 * methodMatcher.hashCode() + ByteBuddy.this.hashCode();
}
@Override
public String toString() {
return "ByteBuddy.MatchedMethodInterception{" +
"methodMatcher=" + methodMatcher +
"byteBuddy=" + ByteBuddy.this.toString() +
'}';
}
}
}