package net.bytebuddy.dynamic;
import edu.umd.cs.findbugs.annotations.
SuppressFBWarnings;
import net.bytebuddy.
ClassFileVersion;
import net.bytebuddy.asm.
AsmVisitorWrapper;
import net.bytebuddy.build.
HashCodeAndEqualsPlugin;
import net.bytebuddy.description.annotation.
AnnotationDescription;
import net.bytebuddy.description.annotation.
AnnotationList;
import net.bytebuddy.description.annotation.
AnnotationValue;
import net.bytebuddy.description.field.
FieldDescription;
import net.bytebuddy.description.method.
MethodDescription;
import net.bytebuddy.description.method.
ParameterDescription;
import net.bytebuddy.description.method.
ParameterList;
import net.bytebuddy.description.modifier.*;
import net.bytebuddy.description.type.
TypeDefinition;
import net.bytebuddy.description.type.
TypeDescription;
import net.bytebuddy.description.type.
TypeList;
import net.bytebuddy.description.type.
TypeVariableToken;
import net.bytebuddy.dynamic.loading.
ClassLoadingStrategy;
import net.bytebuddy.dynamic.loading.
InjectionClassLoader;
import net.bytebuddy.dynamic.scaffold.*;
import net.bytebuddy.implementation.*;
import net.bytebuddy.implementation.attribute.*;
import net.bytebuddy.implementation.auxiliary.
AuxiliaryType;
import net.bytebuddy.implementation.bytecode.
ByteCodeAppender;
import net.bytebuddy.matcher.
ElementMatcher;
import net.bytebuddy.matcher.
LatentMatcher;
import net.bytebuddy.pool.
TypePool;
import net.bytebuddy.utility.
CompoundList;
import java.io.*;
import java.lang.annotation.
Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.jar.*;
import static net.bytebuddy.matcher.
ElementMatchers.*;
/**
* A dynamic type that is created at runtime, usually as the result of applying a
* {@link net.bytebuddy.dynamic.DynamicType.Builder} or as the result of an
* {@link net.bytebuddy.implementation.auxiliary.AuxiliaryType}.
* <p> </p>
* Note that the {@link TypeDescription}s will represent their
* unloaded forms and therefore differ from the loaded types, especially with regards to annotations.
*/
public interface
DynamicType {
/**
* <p>
* Returns a description of this dynamic type.
* </p>
* <p>
* <b>Note</b>: This description will most likely differ from the binary representation of this type. Normally,
* annotations and intercepted methods are not added to this type description.
* </p>
*
* @return A description of this dynamic type.
*/
TypeDescription getTypeDescription();
/**
* Returns a byte array representing this dynamic type. This byte array might be reused by this dynamic type and
* must therefore not be altered.
*
* @return A byte array of the type's binary representation.
*/
byte[]
getBytes();
/**
* <p>
* Returns a map of all auxiliary types that are required for making use of the main type.
* </p>
* <p>
* <b>Note</b>: The type descriptions will most likely differ from the binary representation of this type.
* Normally, annotations and intercepted methods are not added to the type descriptions of auxiliary types.
* </p>
*
* @return A map of all auxiliary types by their descriptions to their binary representation.
*/
Map<
TypeDescription, byte[]>
getAuxiliaryTypes();
/**
* Returns all types that are implied by this dynamic type.
*
* @return A mapping from all type descriptions, the actual type and its auxiliary types to their binary
* representation
*/
Map<
TypeDescription, byte[]>
getAllTypes();
/**
* <p>
* Returns a map of all loaded type initializers for the main type and all auxiliary types, if any.
* </p>
* <p>
* <b>Note</b>: The type descriptions will most likely differ from the binary representation of this type.
* Normally, annotations and intercepted methods are not added to the type descriptions of auxiliary types.
* </p>
*
* @return A mapping of all types' descriptions to their loaded type initializers.
*/
Map<
TypeDescription,
LoadedTypeInitializer>
getLoadedTypeInitializers();
/**
* Checks if a dynamic type requires some form of explicit type initialization, either for itself or for one
* of its auxiliary types, if any. This is the case when this dynamic type was defined to delegate method calls
* to a specific instance which is stored in a field of the created type. If this class serialized, it could not
* be used without its loaded type initializers since the field value represents a specific runtime context.
*
* @return {@code true} if this type requires explicit type initialization.
*/
boolean
hasAliveLoadedTypeInitializers();
/**
* <p>
* Saves a dynamic type in a given folder using the Java class file format while respecting the naming conventions
* for saving compiled Java classes. All auxiliary types, if any, are saved in the same directory. The resulting
* folder structure will resemble the structure that is required for Java run times, i.e. each folder representing
* a segment of the package name. If the specified {@code folder} does not yet exist, it is created during the
* call of this method.
* </p>
* <p>
* <b>Note</b>: The type descriptions will most likely differ from the binary representation of this type.
* Normally, annotations and intercepted methods are not added to the type descriptions of auxiliary types.
* </p>
*
* @param folder The base target folder for storing this dynamic type and its auxiliary types, if any.
* @return A map of type descriptions pointing to files with their stored binary representations within {@code folder}.
* @throws IOException Thrown if the underlying file operations cause an {@code IOException}.
*/
Map<
TypeDescription,
File>
saveIn(
File folder) throws
IOException;
/**
* Injects the types of this dynamic type into a given <i>jar</i> file. Any pre-existent type with the same name
* is overridden during injection. The {@code target} file's folder must exist prior to calling this method. The
* file itself is overwritten or created depending on its prior existence.
*
* @param sourceJar The original jar file.
* @param targetJar The {@code source} jar file with the injected contents.
* @return The {@code target} jar file.
* @throws IOException If an I/O exception occurs while injecting from the source into the target.
*/
File inject(
File sourceJar,
File targetJar) throws
IOException;
/**
* Injects the types of this dynamic type into a given <i>jar</i> file. Any pre-existent type with the same name
* is overridden during injection.
*
* @param jar The jar file to replace with an injected version.
* @return The {@code jar} file.
* @throws IOException If an I/O exception occurs while injecting into the jar.
*/
File inject(
File jar) throws
IOException;
/**
* Saves the contents of this dynamic type inside a <i>jar</i> file. The folder of the given {@code file} must
* exist prior to calling this method. The jar file is created with a simple manifest that only contains a version
* number.
*
* @param file The target file to which the <i>jar</i> is written to.
* @return The given {@code file}.
* @throws IOException If an I/O exception occurs while writing the file.
*/
File toJar(
File file) throws
IOException;
/**
* Saves the contents of this dynamic type inside a <i>jar</i> file. The folder of the given {@code file} must
* exist prior to calling this method.
*
* @param file The target file to which the <i>jar</i> is written to.
* @param manifest The manifest of the created <i>jar</i>.
* @return The given {@code file}.
* @throws IOException If an I/O exception occurs while writing the file.
*/
File toJar(
File file,
Manifest manifest) throws
IOException;
/**
* A builder for creating a dynamic type.
*
* @param <T> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Builder<T> {
/**
* Applies the supplied {@link AsmVisitorWrapper} onto the {@link net.bytebuddy.jar.asm.ClassVisitor} during building a dynamic type.
* Using an ASM visitor, it is possible to manipulate byte code directly. Byte Buddy does not validate directly created byte code
* and it remains the responsibility of the visitor's implementor to generate legal byte code. If several ASM visitor wrappers
* are registered, they are applied on top of another in their registration order.
*
* @param asmVisitorWrapper The ASM visitor wrapper to apply during
* @return A new builder that is equal to this builder and applies the ASM visitor wrapper.
*/
Builder<T>
visit(
AsmVisitorWrapper asmVisitorWrapper);
/**
* Names the dynamic type by the supplied name. The name needs to be fully qualified and in the binary format (packages separated
* by dots: {@code foo.Bar}). A type's package determines what other types are visible to the instrumented type and what methods
* can be overridden or be represented in method signatures or as field types.
*
* @param name The fully qualified name of the generated class in a binary format.
* @return A new builder that is equal to this builder but with the instrumented type named by the supplied name.
*/
Builder<T>
name(
String name);
/**
* Defines the supplied modifiers as the modifiers of the instrumented type.
*
* @param modifierContributor The modifiers of the instrumented type.
* @return A new builder that is equal to this builder but with the supplied modifiers applied onto the instrumented type.
*/
Builder<T>
modifiers(
ModifierContributor.
ForType...
modifierContributor);
/**
* Defines the supplied modifiers as the modifiers of the instrumented type.
*
* @param modifierContributors The modifiers of the instrumented type.
* @return A new builder that is equal to this builder but with the supplied modifiers applied onto the instrumented type.
*/
Builder<T>
modifiers(
Collection<? extends
ModifierContributor.
ForType>
modifierContributors);
/**
* Defines the supplied modifiers as the modifiers of the instrumented type.
*
* @param modifiers The modifiers of the instrumented type.
* @return A new builder that is equal to this builder but with the supplied modifiers applied onto the instrumented type.
*/
Builder<T>
modifiers(int
modifiers);
/**
* Merges the supplied modifier contributors with the modifiers of the instrumented type and defines them as the instrumented
* type's new modifiers.
*
* @param modifierContributor The modifiers of the instrumented type.
* @return A new builder that is equal to this builder but with the supplied modifiers merged into the instrumented type's modifiers.
*/
Builder<T>
merge(
ModifierContributor.
ForType...
modifierContributor);
/**
* Merges the supplied modifier contributors with the modifiers of the instrumented type and defines them as the instrumented
* type's new modifiers.
*
* @param modifierContributors The modifiers of the instrumented type.
* @return A new builder that is equal to this builder but with the supplied modifiers merged into the instrumented type's modifiers.
*/
Builder<T>
merge(
Collection<? extends
ModifierContributor.
ForType>
modifierContributors);
/**
* <p>
* Defines this type as a top-level type that is not declared by another type or enclosed by another member.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @return A new builder that is equal to this builder but without any declaration of a a declared or enclosed type.
*/
Builder<T>
topLevelType();
/**
* <p>
* Defines this type as an inner type of the supplied type. Without any additional configuration, the type declaration is defined
* as a local type.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The type to declare as the built type's outer type.
* @return A new builder that is equal to this builder with the supplied type as the built type's outer type.
*/
InnerTypeDefinition.
ForType<T>
innerTypeOf(
Class<?>
type);
/**
* <p>
* Defines this type as an inner type of the supplied type. Without any additional configuration, the type declaration is
* defined as a local type.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The type to declare as the built type's outer type.
* @return A new builder that is equal to this builder with the supplied type as the built type's outer type.
*/
InnerTypeDefinition.
ForType<T>
innerTypeOf(
TypeDescription type);
/**
* <p>
* Defines this type as an inner type that was declared within the supplied method. Without any additional configuration, the type
* declaration is defined as a local type.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param method The method to declare as the built type's declaring method.
* @return A new builder that is equal to this builder with the supplied method as the built type's declaring method.
*/
InnerTypeDefinition<T>
innerTypeOf(
Method method);
/**
* <p>
* Defines this type as an inner type that was declared within the supplied constructor. Without any additional configuration, the type
* declaration is defined as a local type.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param constructor The constructor to declare as the built type's declaring method.
* @return A new builder that is equal to this builder with the supplied method as the built type's declaring constructor.
*/
InnerTypeDefinition<T>
innerTypeOf(
Constructor<?>
constructor);
/**
* <p>
* Defines this type as an inner type that was declared within the supplied method or constructor. Without any additional configuration,
* the type declaration is defined as a local type.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param methodDescription The method or constructor to declare as the built type's declaring method.
* @return A new builder that is equal to this builder with the supplied method as the built type's declaring method or constructor.
*/
InnerTypeDefinition<T>
innerTypeOf(
MethodDescription.
InDefinedShape methodDescription);
/**
* <p>
* Defines this type as an the outer type of the supplied types. Using this method, it is possible to add inner type declarations
* for anonymous or local types which are not normally exposed by type descriptions. Doing so, it is however possible to indicate to
* Byte Buddy that the required attributes for such an inner type declaration should be added to a class file.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The types being declared.
* @return A new builder that is equal to this builder with the supplied types being declared by the built type.
*/
Builder<T>
declaredTypes(
Class<?>...
type);
/**
* <p>
* Defines this type as an the outer type of the supplied types. Using this method, it is possible to add inner type declarations
* for anonymous or local types which are not normally exposed by type descriptions. Doing so, it is however possible to indicate to
* Byte Buddy that the required attributes for such an inner type declaration should be added to a class file.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The types being declared.
* @return A new builder that is equal to this builder with the supplied types being declared by the built type.
*/
Builder<T>
declaredTypes(
TypeDescription...
type);
/**
* <p>
* Defines this type as an the outer type of the supplied types. Using this method, it is possible to add inner type declarations
* for anonymous or local types which are not normally exposed by type descriptions. Doing so, it is however possible to indicate to
* Byte Buddy that the required attributes for such an inner type declaration should be added to a class file.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param types The types being declared.
* @return A new builder that is equal to this builder with the supplied types being declared by the built type.
*/
Builder<T>
declaredTypes(
List<? extends
Class<?>>
types);
/**
* <p>
* Defines this type as an the outer type of the supplied types. Using this method, it is possible to add inner type declarations
* for anonymous or local types which are not normally exposed by type descriptions. Doing so, it is however possible to indicate to
* Byte Buddy that the required attributes for such an inner type declaration should be added to a class file.
* </p>
* <p>
* <b>Important</b>: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy.
* </p>
* <p>
* <b>Warning</b>: By changing this type's declaration, any other type will not change its declaration of enclosing members or
* declared types about any nesting of a declaration. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param types The types being declared.
* @return A new builder that is equal to this builder with the supplied types being declared by the built type.
*/
Builder<T>
declaredTypes(
Collection<? extends
TypeDescription>
types);
/**
* <p>
* Defines this type as self-hosted, i.e. as only being a nest mate of itself.
* </p>
* <p>
* <b>Important</b>: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy.
* </p>
* <p>
* <b>Warning</b>: Changing nest mate hierarchies always requires changing a member and its host or a host and all its members.
* Otherwise, the runtime will not accept further nest mates. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @return A new builder that is equal to this builder but where the built type is a self-hosted nest mate.
*/
Builder<T>
noNestMate();
/**
* <p>
* Defines this type as a nest member of the supplied type as a nest host.
* </p>
* <p>
* <b>Important</b>: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy.
* </p>
* <p>
* <b>Warning</b>: Changing nest mate hierarchies always requires changing a member and its host or a host and all its members.
* Otherwise, the runtime will not accept further nest mates. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The nest host.
* @return A new builder that is equal to this builder but where the built type is a nest member of the supplied host.
*/
Builder<T>
nestHost(
Class<?>
type);
/**
* <p>
* Defines this type as a nest member of the supplied type as a nest host.
* </p>
* <p>
* <b>Important</b>: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy.
* </p>
* <p>
* <b>Warning</b>: Changing nest mate hierarchies always requires changing a member and its host or a host and all its members.
* Otherwise, the runtime will not accept further nest mates. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The nest host.
* @return A new builder that is equal to this builder but where the built type is a nest member of the supplied host.
*/
Builder<T>
nestHost(
TypeDescription type);
/**
* <p>
* Defines this type as a nest host for the supplied types.
* </p>
* <p>
* <b>Important</b>: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy.
* </p>
* <p>
* <b>Warning</b>: Changing nest mate hierarchies always requires changing a member and its host or a host and all its members.
* Otherwise, the runtime will not accept further nest mates. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The nest members.
* @return A new builder that is equal to this builder but where the built type is a nest host of the supplied types.
*/
Builder<T>
nestMembers(
Class<?>...
type);
/**
* <p>
* Defines this type as a nest host for the supplied types.
* </p>
* <p>
* <b>Important</b>: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy.
* </p>
* <p>
* <b>Warning</b>: Changing nest mate hierarchies always requires changing a member and its host or a host and all its members.
* Otherwise, the runtime will not accept further nest mates. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param type The nest members.
* @return A new builder that is equal to this builder but where the built type is a nest host of the supplied types.
*/
Builder<T>
nestMembers(
TypeDescription...
type);
/**
* <p>
* Defines this type as a nest host for the supplied types.
* </p>
* <p>
* <b>Important</b>: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy.
* </p>
* <p>
* <b>Warning</b>: Changing nest mate hierarchies always requires changing a member and its host or a host and all its members.
* Otherwise, the runtime will not accept further nest mates. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param types The nest members.
* @return A new builder that is equal to this builder but where the built type is a nest host of the supplied types.
*/
Builder<T>
nestMembers(
List<? extends
Class<?>>
types);
/**
* <p>
* Defines this type as a nest host for the supplied types.
* </p>
* <p>
* <b>Important</b>: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy.
* </p>
* <p>
* <b>Warning</b>: Changing nest mate hierarchies always requires changing a member and its host or a host and all its members.
* Otherwise, the runtime will not accept further nest mates. It is the responsibility of the user of this API to keep such declarations
* consistent among the definitions of connected types.
* </p>
*
* @param types The nest members.
* @return A new builder that is equal to this builder but where the built type is a nest host of the supplied types.
*/
Builder<T>
nestMembers(
Collection<? extends
TypeDescription>
types);
/**
* Applies the given type attribute appender onto the instrumented type. Using a type attribute appender, it is possible to append
* any type of meta data to a type, not only Java {@link Annotation}s.
*
* @param typeAttributeAppender The type attribute appender to apply.
* @return A new builder that is equal to this builder but with the supplied type attribute appender applied to the instrumented type.
*/
Builder<T>
attribute(
TypeAttributeAppender typeAttributeAppender);
/**
* Annotates the instrumented type with the supplied annotations.
*
* @param annotation The annotations to add to the instrumented type.
* @return A new builder that is equal to this builder but with the annotations added to the instrumented type.
*/
Builder<T>
annotateType(
Annotation...
annotation);
/**
* Annotates the instrumented type with the supplied annotations.
*
* @param annotations The annotations to add to the instrumented type.
* @return A new builder that is equal to this builder but with the annotations added to the instrumented type.
*/
Builder<T>
annotateType(
List<? extends
Annotation>
annotations);
/**
* Annotates the instrumented type with the supplied annotations.
*
* @param annotation The annotations to add to the instrumented type.
* @return A new builder that is equal to this builder but with the annotations added to the instrumented type.
*/
Builder<T>
annotateType(
AnnotationDescription...
annotation);
/**
* Annotates the instrumented type with the supplied annotations.
*
* @param annotations The annotations to add to the instrumented type.
* @return A new builder that is equal to this builder but with the annotations added to the instrumented type.
*/
Builder<T>
annotateType(
Collection<? extends
AnnotationDescription>
annotations);
/**
* <p>
* Implements the supplied interfaces for the instrumented type. Optionally, it is possible to define the
* methods that are defined by the interfaces or the interfaces' super interfaces. This excludes methods that
* are explicitly ignored.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables or an owner type.
* </p>
*
* @param interfaceType The interface types to implement.
* @return A new builder that is equal to this builder but with the interfaces implemented by the instrumented type.
*/
MethodDefinition.
ImplementationDefinition.
Optional<T>
implement(
Type...
interfaceType);
/**
* <p>
* Implements the supplied interfaces for the instrumented type. Optionally, it is possible to define the
* methods that are defined by the interfaces or the interfaces' super interfaces. This excludes methods that
* are explicitly ignored.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables or an owner type.
* </p>
*
* @param interfaceTypes The interface types to implement.
* @return A new builder that is equal to this builder but with the interfaces implemented by the instrumented type.
*/
MethodDefinition.
ImplementationDefinition.
Optional<T>
implement(
List<? extends
Type>
interfaceTypes);
/**
* <p>
* Implements the supplied interfaces for the instrumented type. Optionally, it is possible to define the
* methods that are defined by the interfaces or the interfaces' super interfaces. This excludes methods that
* are explicitly ignored.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are
* implemented as raw types if they declare type variables or an owner type.
* </p>
*
* @param interfaceType The interface types to implement.
* @return A new builder that is equal to this builder but with the interfaces implemented by the instrumented type.
*/
MethodDefinition.
ImplementationDefinition.
Optional<T>
implement(
TypeDefinition...
interfaceType);
/**
* <p>
* Implements the supplied interfaces for the instrumented type. Optionally, it is possible to define the
* methods that are defined by the interfaces or the interfaces' super interfaces. This excludes methods that
* are explicitly ignored.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are
* implemented as raw types if they declare type variables or an owner type.
* </p>
*
* @param interfaceTypes The interface types to implement.
* @return A new builder that is equal to this builder but with the interfaces implemented by the instrumented type.
*/
MethodDefinition.
ImplementationDefinition.
Optional<T>
implement(
Collection<? extends
TypeDefinition>
interfaceTypes);
/**
* <p>
* Executes the supplied byte code appender within the beginning of the instrumented type's type initializer. The
* supplied byte code appender <b>must not return</b> from the method. If several byte code appenders are supplied,
* they are executed within their application order.
* </p>
* <p>
* This method should only be used for preparing an instrumented type with a specific configuration. Normally,
* a byte code appender is applied via Byte Buddy's standard API by invoking {@link Builder#invokable(ElementMatcher)}
* using the {@link net.bytebuddy.matcher.ElementMatchers#isTypeInitializer()} matcher.
* </p>
*
* @param byteCodeAppender The byte code appender to execute within the instrumented type's type initializer.
* @return A new builder that is equal to this builder but with the supplied byte code appender being executed within
* the instrumented type's type initializer.
*/
Builder<T>
initializer(
ByteCodeAppender byteCodeAppender);
/**
* Executes the supplied loaded type initializer when loading the created instrumented type. If several loaded
* type initializers are supplied, each loaded type initializer is executed in its registration order.
*
* @param loadedTypeInitializer The loaded type initializer to execute upon loading the instrumented type.
* @return A new builder that is equal to this builder but with the supplied loaded type initializer executed upon
* loading the instrumented type.
*/
Builder<T>
initializer(
LoadedTypeInitializer loadedTypeInitializer);
/**
* Explicitly requires another dynamic type for the creation of this type.
*
* @param type The type to require.
* @param binaryRepresentation The type's binary representation.
* @return A new builder that is equal to this builder but which explicitly requires the supplied type.
*/
Builder<T>
require(
TypeDescription type, byte[]
binaryRepresentation);
/**
* Explicitly requires another dynamic type for the creation of this type.
*
* @param type The type to require.
* @param binaryRepresentation The type's binary representation.
* @param typeInitializer The type's loaded type initializer.
* @return A new builder that is equal to this builder but which explicitly requires the supplied type.
*/
Builder<T>
require(
TypeDescription type, byte[]
binaryRepresentation,
LoadedTypeInitializer typeInitializer);
/**
* Explicitly requires other dynamic types for the creation of this type.
*
* @param auxiliaryType The required dynamic types.
* @return A new builder that is equal to this builder but which explicitly requires the supplied types.
*/
Builder<T>
require(
DynamicType...
auxiliaryType);
/**
* Explicitly requires other dynamic types for the creation of this type.
*
* @param auxiliaryTypes The required dynamic types.
* @return A new builder that is equal to this builder but which explicitly requires the supplied types.
*/
Builder<T>
require(
Collection<
DynamicType>
auxiliaryTypes);
/**
* Defines the supplied type variable without any bounds as a type variable of the instrumented type.
*
* @param symbol The type variable's symbol.
* @return A new builder that is equal to this builder but with the given type variable defined for the instrumented type.
*/
TypeVariableDefinition<T>
typeVariable(
String symbol);
/**
* Defines the supplied type variable with the given bound as a type variable of the instrumented type.
*
* @param symbol The type variable's symbol.
* @param bound The type variable's upper bounds. Can also be {@link net.bytebuddy.dynamic.TargetType} if the bound type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to this builder but with the given type variable defined for the instrumented type.
*/
TypeVariableDefinition<T>
typeVariable(
String symbol,
Type...
bound);
/**
* Defines the supplied type variable with the given bound as a type variable of the instrumented type.
*
* @param symbol The type variable's symbol.
* @param bounds The type variable's upper bounds. Can also be {@link net.bytebuddy.dynamic.TargetType} if the bound type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to this builder but with the given type variable defined for the instrumented type.
*/
TypeVariableDefinition<T>
typeVariable(
String symbol,
List<? extends
Type>
bounds);
/**
* Defines the supplied type variable with the given bound as a type variable of the instrumented type.
*
* @param symbol The type variable's symbol.
* @param bound The type variable's upper bounds. Can also be {@link net.bytebuddy.dynamic.TargetType} if the bound type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to this builder but with the given type variable defined for the instrumented type.
*/
TypeVariableDefinition<T>
typeVariable(
String symbol,
TypeDefinition...
bound);
/**
* Defines the supplied type variable with the given bound as a type variable of the instrumented type.
*
* @param symbol The type variable's symbol.
* @param bounds The type variable's upper bounds. Can also be {@link net.bytebuddy.dynamic.TargetType} if the bound type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to this builder but with the given type variable defined for the instrumented type.
*/
TypeVariableDefinition<T>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds);
/**
* Transforms any type variable that is defined by this type if it is matched by the supplied matcher.
*
* @param matcher The matcher to decide what type variables to transform.
* @param transformer The transformer to apply to the matched type variables.
* @return A new builder that is equal to this builder but with the supplied transformer applied to all type variables.
*/
Builder<T>
transform(
ElementMatcher<? super
TypeDescription.
Generic>
matcher,
Transformer<
TypeVariableToken>
transformer);
/**
* Defines the specified field as a field of the built dynamic type.
*
* @param name The name of the field.
* @param type The type of the field. Can also be {@link net.bytebuddy.dynamic.TargetType} if the field type
* should be equal to the currently instrumented type.
* @param modifierContributor The modifiers of the field.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
defineField(
String name,
Type type,
ModifierContributor.
ForField...
modifierContributor);
/**
* Defines the specified field as a field of the built dynamic type.
*
* @param name The name of the field.
* @param type The type of the field. Can also be {@link net.bytebuddy.dynamic.TargetType} if the field type
* should be equal to the currently instrumented type.
* @param modifierContributors The modifiers of the field.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
defineField(
String name,
Type type,
Collection<? extends
ModifierContributor.
ForField>
modifierContributors);
/**
* Defines the specified field as a field of the built dynamic type.
*
* @param name The name of the field.
* @param type The type of the field. Can also be {@link net.bytebuddy.dynamic.TargetType} if the field type
* should be equal to the currently instrumented type.
* @param modifiers The modifiers of the field.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
defineField(
String name,
Type type, int
modifiers);
/**
* Defines the specified field as a field of the built dynamic type.
*
* @param name The name of the field.
* @param type The type of the field. Can also be {@link net.bytebuddy.dynamic.TargetType} if the field type
* should be equal to the currently instrumented type.
* @param modifierContributor The modifiers of the field.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
defineField(
String name,
TypeDefinition type,
ModifierContributor.
ForField...
modifierContributor);
/**
* Defines the specified field as a field of the built dynamic type.
*
* @param name The name of the field.
* @param type The type of the field. Can also be {@link net.bytebuddy.dynamic.TargetType} if the field type
* should be equal to the currently instrumented type.
* @param modifierContributors The modifiers of the field.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
defineField(
String name,
TypeDefinition type,
Collection<? extends
ModifierContributor.
ForField>
modifierContributors);
/**
* Defines the specified field as a field of the built dynamic type.
*
* @param name The name of the field.
* @param type The type of the field. Can also be {@link net.bytebuddy.dynamic.TargetType} if the field type
* should be equal to the currently instrumented type.
* @param modifiers The modifiers of the field.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
defineField(
String name,
TypeDefinition type, int
modifiers);
/**
* Defines a field that is similar to the supplied field but without copying any annotations on the field.
*
* @param field The field to imitate as a field of the instrumented type.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
define(
Field field);
/**
* Defines a field that is similar to the supplied field but without copying any annotations on the field.
*
* @param field The field to imitate as a field of the instrumented type.
* @return A new builder that is equal to this builder but with the given field defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional.
Valuable<T>
define(
FieldDescription field);
/**
* Defines a private, static, final field for a serial version UID of the given value.
*
* @param serialVersionUid The serial version UID to define as a value.
* @return A new builder that is equal to this builder but with the given type variable defined for the instrumented type.
* Furthermore, it is possible to optionally define a value, annotations or custom attributes for the field.
*/
FieldDefinition.
Optional<T>
serialVersionUid(long
serialVersionUid);
/**
* <p>
* Matches a field that is already declared by the instrumented type. This gives opportunity to change that field's
* default value, annotations or custom attributes.
* </p>
* <p>
* When a type is redefined or rebased, any annotations that the field declared previously is preserved
* <i>as it is</i> if Byte Buddy is configured to retain such annotations by
* {@link net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be
* altered, annotation retention must be disabled.
* </p>
* <p>
* If a field is already matched by a previously specified field matcher, the new field definition gets precedence
* over the previous definition, i.e. the previous field definition is no longer applied.
* </p>
*
* @param matcher The matcher that determines what declared fields are affected by the subsequent specification.
* @return A builder that allows for changing a field's definition.
*/
FieldDefinition.
Valuable<T>
field(
ElementMatcher<? super
FieldDescription>
matcher);
/**
* <p>
* Matches a field that is already declared by the instrumented type. This gives opportunity to change that field's
* default value, annotations or custom attributes. Using a latent matcher gives opportunity to resolve an
* {@link ElementMatcher} based on the instrumented type before applying the matcher.
* </p>
* <p>
* When a type is redefined or rebased, any annotations that the field declared previously is preserved
* <i>as it is</i> if Byte Buddy is configured to retain such annotations by
* {@link net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be
* altered, annotation retention must be disabled.
* </p>
* <p>
* If a field is already matched by a previously specified field matcher, the new field definition gets precedence
* over the previous definition, i.e. the previous field definition is no longer applied.
* </p>
*
* @param matcher The matcher that determines what declared fields are affected by the subsequent specification.
* @return A builder that allows for changing a field's definition.
*/
FieldDefinition.
Valuable<T>
field(
LatentMatcher<? super
FieldDescription>
matcher);
/**
* <p>
* Specifies to exclude any method that is matched by the supplied matcher from instrumentation. Previously supplied matchers
* remain valid after supplying a new matcher, i.e. any method that is matched by a previously supplied matcher is always ignored.
* </p>
* <p>
* When ignoring a type, previously registered matchers are applied before this matcher. If a previous matcher indicates that a type
* is to be ignored, this matcher is no longer executed.
* </p>
*
* @param ignoredMethods The matcher for determining what methods to exclude from instrumentation.
* @return A new builder that is equal to this builder but that is excluding any method that is matched by the supplied matcher from
* instrumentation.
*/
Builder<T>
ignoreAlso(
ElementMatcher<? super
MethodDescription>
ignoredMethods);
/**
* <p>
* Specifies to exclude any method that is matched by the supplied matcher from instrumentation. Previously supplied matchers
* remain valid after supplying a new matcher, i.e. any method that is matched by a previously supplied matcher is always ignored.
* Using a latent matcher gives opportunity to resolve an {@link ElementMatcher} based on the instrumented type before applying the
* matcher.
* </p>
* <p>
* When ignoring a type, previously registered matchers are applied before this matcher. If a previous matcher indicates that a type
* is to be ignored, this matcher is no longer executed.
* </p>
*
* @param ignoredMethods The matcher for determining what methods to exclude from instrumentation.
* @return A new builder that is equal to this builder but that is excluding any method that is matched by the supplied matcher from
* instrumentation.
*/
Builder<T>
ignoreAlso(
LatentMatcher<? super
MethodDescription>
ignoredMethods);
/**
* Defines the specified method to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param name The name of the method.
* @param returnType The method's return type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the return type
* should be equal to the currently instrumented type.
* @param modifierContributor The method's modifiers.
* @return A builder that allows for further defining the method, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineMethod(
String name,
Type returnType,
ModifierContributor.
ForMethod...
modifierContributor);
/**
* Defines the specified method to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param name The name of the method.
* @param returnType The method's return type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the return type
* should be equal to the currently instrumented type.
* @param modifierContributors The method's modifiers.
* @return A builder that allows for further defining the method, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineMethod(
String name,
Type returnType,
Collection<? extends
ModifierContributor.
ForMethod>
modifierContributors);
/**
* Defines the specified method to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param name The name of the method.
* @param returnType The method's return type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the return type
* should be equal to the currently instrumented type.
* @param modifiers The method's modifiers.
* @return A builder that allows for further defining the method, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineMethod(
String name,
Type returnType, int
modifiers);
/**
* Defines the specified method to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param name The name of the method.
* @param returnType The method's return type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the return type
* should be equal to the currently instrumented type.
* @param modifierContributor The method's modifiers.
* @return A builder that allows for further defining the method, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineMethod(
String name,
TypeDefinition returnType,
ModifierContributor.
ForMethod...
modifierContributor);
/**
* Defines the specified method to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param name The name of the method.
* @param returnType The method's return type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the return type
* should be equal to the currently instrumented type.
* @param modifierContributors The method's modifiers.
* @return A builder that allows for further defining the method, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineMethod(
String name,
TypeDefinition returnType,
Collection<? extends
ModifierContributor.
ForMethod>
modifierContributors);
/**
* Defines the specified method to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param name The name of the method.
* @param returnType The method's return type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the return type
* should be equal to the currently instrumented type.
* @param modifiers The method's modifiers.
* @return A builder that allows for further defining the method, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineMethod(
String name,
TypeDefinition returnType, int
modifiers);
/**
* Defines the specified constructor to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param modifierContributor The constructor's modifiers.
* @return A builder that allows for further defining the constructor, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineConstructor(
ModifierContributor.
ForMethod...
modifierContributor);
/**
* Defines the specified constructor to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param modifierContributors The constructor's modifiers.
* @return A builder that allows for further defining the constructor, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineConstructor(
Collection<? extends
ModifierContributor.
ForMethod>
modifierContributors);
/**
* Defines the specified constructor to be declared by the instrumented type. Method parameters or parameter types, declared exceptions and
* type variables can be defined in subsequent steps.
*
* @param modifiers The constructor's modifiers.
* @return A builder that allows for further defining the constructor, either by adding more properties or by defining an implementation.
*/
MethodDefinition.
ParameterDefinition.
Initial<T>
defineConstructor(int
modifiers);
/**
* Defines a method that is similar to the supplied method but without copying any annotations of the method or method parameters.
*
* @param method The method to imitate as a method of the instrumented type.
* @return A builder that allows for defining an implementation for the method.
*/
MethodDefinition.
ImplementationDefinition<T>
define(
Method method);
/**
* Defines a constructor that is similar to the supplied constructor but without copying any annotations of the constructor or
* constructor parameters.
*
* @param constructor The constructor to imitate as a method of the instrumented type.
* @return A builder that allows for defining an implementation for the constructor.
*/
MethodDefinition.
ImplementationDefinition<T>
define(
Constructor<?>
constructor);
/**
* Defines a method or constructor that is similar to the supplied method description but without copying any annotations of
* the method/constructor or method/constructor parameters.
*
* @param methodDescription The method description to imitate as a method or constructor of the instrumented type.
* @return A builder that allows for defining an implementation for the method or constructor.
*/
MethodDefinition.
ImplementationDefinition<T>
define(
MethodDescription methodDescription);
/**
* Defines a Java bean property with the specified name.
*
* @param name The name of the property.
* @param type The property type.
* @return A builder that defines the specified property where the field holding the property can be refined by subsequent steps.
*/
FieldDefinition.
Optional<T>
defineProperty(
String name,
Type type);
/**
* Defines a Java bean property with the specified name.
*
* @param name The name of the property.
* @param type The property type.
* @param readOnly {@code true} if the property is read only, i.e. no setter should be defined and the field should be {@code final}.
* @return A builder that defines the specified property where the field holding the property can be refined by subsequent steps.
*/
FieldDefinition.
Optional<T>
defineProperty(
String name,
Type type, boolean
readOnly);
/**
* Defines a Java bean property with the specified name.
*
* @param name The name of the property.
* @param type The property type.
* @return A builder that defines the specified property where the field holding the property can be refined by subsequent steps.
*/
FieldDefinition.
Optional<T>
defineProperty(
String name,
TypeDefinition type);
/**
* Defines a Java bean property with the specified name.
*
* @param name The name of the property.
* @param type The property type.
* @param readOnly {@code true} if the property is read only, i.e. no setter should be defined and the field should be {@code final}.
* @return A builder that defines the specified property where the field holding the property can be refined by subsequent steps.
*/
FieldDefinition.
Optional<T>
defineProperty(
String name,
TypeDefinition type, boolean
readOnly);
/**
* <p>
* Matches a method that is already declared or inherited by the instrumented type. This gives opportunity to change or to
* override that method's implementation, default value, annotations or custom attributes. It is also possible to make
* a method abstract.
* </p>
* <p>
* When a type is redefined or rebased, any annotations that the method declared previously is preserved
* <i>as it is</i> if Byte Buddy is configured to retain such annotations by
* {@link net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be
* altered, annotation retention must be disabled.
* </p>
* <p>
* If a method is already matched by a previously specified matcher, the new method definition gets precedence
* over the previous definition, i.e. the previous method definition is no longer applied.
* </p>
* <p>
* Note that the specified definition does never apply for methods that are explicitly ignored.
* </p>
*
* @param matcher The matcher that determines what methods are affected by the subsequent specification.
* @return A builder that allows for changing a method's or constructor's definition.
*/
MethodDefinition.
ImplementationDefinition<T>
method(
ElementMatcher<? super
MethodDescription>
matcher);
/**
* <p>
* Matches a constructor that is already declared by the instrumented type. This gives opportunity to change that constructor's
* implementation, default value, annotations or custom attributes.
* </p>
* <p>
* When a type is redefined or rebased, any annotations that the constructor declared previously is preserved
* <i>as it is</i> if Byte Buddy is configured to retain such annotations by
* {@link net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be
* altered, annotation retention must be disabled.
* </p>
* <p>
* If a constructor is already matched by a previously specified matcher, the new constructor definition gets precedence
* over the previous definition, i.e. the previous constructor definition is no longer applied.
* </p>
* <p>
* Note that the specified definition does never apply for methods that are explicitly ignored.
* </p>
*
* @param matcher The matcher that determines what constructors are affected by the subsequent specification.
* @return A builder that allows for changing a method's or constructor's definition.
*/
MethodDefinition.
ImplementationDefinition<T>
constructor(
ElementMatcher<? super
MethodDescription>
matcher);
/**
* <p>
* Matches a method or constructor that is already declared or inherited by the instrumented type. This gives
* opportunity to change or to override that method's or constructor's implementation, default value, annotations
* or custom attributes. It is also possible to make a method abstract.
* </p>
* <p>
* When a type is redefined or rebased, any annotations that the method or constructor declared previously is preserved
* <i>as it is</i> if Byte Buddy is configured to retain such annotations by
* {@link net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be
* altered, annotation retention must be disabled.
* </p>
* <p>
* If a method or constructor is already matched by a previously specified matcher, the new definition gets precedence
* over the previous definition, i.e. the previous definition is no longer applied.
* </p>
* <p>
* Note that the specified definition does never apply for methods that are explicitly ignored.
* </p>
* <p>
* <b>Important</b>: It is possible to instrument the dynamic type's initializer. Depending on the used {@link TypeResolutionStrategy},
* the type initializer might be run <b>before</b> Byte Buddy could apply any {@link LoadedTypeInitializer}s which are
* responsible for preparing the instrumented type prior to the initializer's execution. For preparing the type prior to
* executing the initializer, an {@link TypeResolutionStrategy.Active} resolver must be chosen.
* </p>
*
* @param matcher The matcher that determines what methods or constructors are affected by the subsequent specification.
* @return A builder that allows for changing a method's or constructor's definition.
*/
MethodDefinition.
ImplementationDefinition<T>
invokable(
ElementMatcher<? super
MethodDescription>
matcher);
/**
* <p>
* Matches a method or constructor that is already declared or inherited by the instrumented type. This gives
* opportunity to change or to override that method's or constructor's implementation, default value, annotations
* or custom attributes. It is also possible to make a method abstract. Using a latent matcher gives opportunity
* to resolve an {@link ElementMatcher} based on the instrumented type before applying the matcher.
* </p>
* <p>
* When a type is redefined or rebased, any annotations that the method or constructor declared previously is preserved
* <i>as it is</i> if Byte Buddy is configured to retain such annotations by
* {@link net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be
* altered, annotation retention must be disabled.
* </p>
* <p>
* If a method or constructor is already matched by a previously specified matcher, the new definition gets precedence
* over the previous definition, i.e. the previous definition is no longer applied.
* </p>
* <p>
* Note that the specified definition does never apply for methods that are explicitly ignored.
* </p>
* <p>
* <b>Important</b>: It is possible to instrument the dynamic type's initializer. Depending on the used {@link TypeResolutionStrategy},
* the type initializer might be run <b>before</b> Byte Buddy could apply any {@link LoadedTypeInitializer}s which are
* responsible for preparing the instrumented type prior to the initializer's execution. For preparing the type prior to
* executing the initializer, an {@link TypeResolutionStrategy.Active} resolver must be chosen.
* </p>
*
* @param matcher The matcher that determines what declared methods or constructors are affected by the subsequent specification.
* @return A builder that allows for changing a method's or constructor's definition.
*/
MethodDefinition.
ImplementationDefinition<T>
invokable(
LatentMatcher<? super
MethodDescription>
matcher);
/**
* Implements {@link Object#hashCode()} and {@link Object#equals(Object)} methods for the instrumented type if those
* methods are not declared as {@code final} by a super class. The implementations do not consider any implementations
* of a super class and compare a class field by field without considering synthetic fields.
*
* @return A new type builder that defines {@link Object#hashCode()} and {@link Object#equals(Object)} methods accordingly.
*/
Builder<T>
withHashCodeEquals();
/**
* Implements a {@link Object#toString()} method for the instrumented type if such a method is not declared as {@code final}
* by a super class. The implementation prefixes the string with the simple class name and prints each non-synthetic field's
* value after the field's name.
*
* @return A new type builder that defines {@link Object#toString()} method accordingly.
*/
Builder<T>
withToString();
/**
* <p>
* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown.
* </p>
* <p>
* Other than {@link DynamicType.Builder#make(TypePool)}, this method supplies a context-dependant type pool to the underlying class writer.
* Supplying a type pool only makes sense if custom byte code is created by adding a custom {@link AsmVisitorWrapper} where ASM might be
* required to compute stack map frames by processing information over any mentioned type's class hierarchy.
* </p>
* <p>
* The dynamic type is initialized using a {@link TypeResolutionStrategy.Passive} strategy. Using this strategy, no
* {@link LoadedTypeInitializer} is run during the execution of the type's initializer such that no {@link Implementation} used for
* executing the initializer must rely on such an initializer.
* </p>
*
* @return An unloaded dynamic type representing the type specified by this builder.
*/
DynamicType.
Unloaded<T>
make();
/**
* <p>
* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown.
* </p>
* <p>
* The dynamic type is initialized using a {@link TypeResolutionStrategy.Passive} strategy. Using this strategy, no
* {@link LoadedTypeInitializer} is run during the execution of the type's initializer such that no {@link Implementation} used for
* executing the initializer must rely on such an initializer.
* </p>
*
* @param typeResolutionStrategy The type resolution strategy to use for the created type's initialization.
* @return An unloaded dynamic type representing the type specified by this builder.
*/
DynamicType.
Unloaded<T>
make(
TypeResolutionStrategy typeResolutionStrategy);
/**
* <p>
* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown.
* </p>
* <p>
* The dynamic type is initialized using a {@link TypeResolutionStrategy.Passive} strategy. Using this strategy, no
* {@link LoadedTypeInitializer} is run during the execution of the type's initializer such that no {@link Implementation} used for
* executing the initializer must rely on such an initializer.
* </p>
*
* @param typePool A type pool that is used for computing stack map frames by the underlying class writer, if required.
* @return An unloaded dynamic type representing the type specified by this builder.
*/
DynamicType.
Unloaded<T>
make(
TypePool typePool);
/**
* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown.
*
* @param typeResolutionStrategy The type resolution strategy to use for the created type's initialization.
* @param typePool A type pool that is used for computing stack map frames by the underlying class writer, if required.
* @return An unloaded dynamic type representing the type specified by this builder.
*/
DynamicType.
Unloaded<T>
make(
TypeResolutionStrategy typeResolutionStrategy,
TypePool typePool);
/**
* An inner type definition for defining a type that is contained within another type, method or constructor.
*
* @param <S> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
InnerTypeDefinition<S> extends
Builder<S> {
/**
* Defines this inner type declaration as an anonymous type.
*
* @return A new builder that is equal to this type builder but that defines the previous inner type definition as a anonymous type.
*/
Builder<S>
asAnonymousType();
/**
* An inner type definition for defining a type that is contained within another type.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
ForType<U> extends
InnerTypeDefinition<U> {
/**
* Defines this inner type declaration as a member type.
*
* @return A new builder that is equal to this type builder but that defines the previous inner type definition as a member type.
*/
Builder<U>
asMemberType();
}
}
/**
* A builder for a type variable definition.
*
* @param <S> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
TypeVariableDefinition<S> extends
Builder<S> {
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
TypeVariableDefinition<S>
annotateTypeVariable(
Annotation...
annotation);
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
TypeVariableDefinition<S>
annotateTypeVariable(
List<? extends
Annotation>
annotations);
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
TypeVariableDefinition<S>
annotateTypeVariable(
AnnotationDescription...
annotation);
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
TypeVariableDefinition<S>
annotateTypeVariable(
Collection<? extends
AnnotationDescription>
annotations);
/**
* An abstract base implementation of a type variable definition.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<U> extends
Builder.
AbstractBase.
Delegator<U> implements
TypeVariableDefinition<U> {
@
Override
public
TypeVariableDefinition<U>
annotateTypeVariable(
Annotation...
annotation) {
return
annotateTypeVariable(
Arrays.
asList(
annotation));
}
@
Override
public
TypeVariableDefinition<U>
annotateTypeVariable(
List<? extends
Annotation>
annotations) {
return
annotateTypeVariable(new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
TypeVariableDefinition<U>
annotateTypeVariable(
AnnotationDescription...
annotation) {
return
annotateTypeVariable(
Arrays.
asList(
annotation));
}
}
}
/**
* A builder for a field definition.
*
* @param <S> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
FieldDefinition<S> {
/**
* Annotates the previously defined or matched field with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined or matched field.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched field.
*/
FieldDefinition.
Optional<S>
annotateField(
Annotation...
annotation);
/**
* Annotates the previously defined or matched field with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined or matched field.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched field.
*/
FieldDefinition.
Optional<S>
annotateField(
List<? extends
Annotation>
annotations);
/**
* Annotates the previously defined or matched field with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined or matched field.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched field.
*/
FieldDefinition.
Optional<S>
annotateField(
AnnotationDescription...
annotation);
/**
* Annotates the previously defined or matched field with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined or matched field.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched field.
*/
FieldDefinition.
Optional<S>
annotateField(
Collection<? extends
AnnotationDescription>
annotations);
/**
* Applies the supplied attribute appender factory onto the previously defined or matched field.
*
* @param fieldAttributeAppenderFactory The field attribute appender factory that should be applied on the
* previously defined or matched field.
* @return A new builder that is equal to this builder but with the supplied field attribute appender factory
* applied to the previously defined or matched field.
*/
FieldDefinition.
Optional<S>
attribute(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory);
/**
* Applies the supplied transformer onto the previously defined or matched field. The transformed
* field is written <i>as it is</i> and it not subject to any validations.
*
* @param transformer The transformer to apply to the previously defined or matched field.
* @return A new builder that is equal to this builder but with the supplied field transformer
* applied to the previously defined or matched field.
*/
FieldDefinition.
Optional<S>
transform(
Transformer<
FieldDescription>
transformer);
/**
* A builder for a field definition that allows for defining a value.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Valuable<U> extends
FieldDefinition<U> {
/**
* <p>
* Defines the supplied {@code boolean} value as a default value of the previously defined or matched field. The value can only
* be set for numeric fields of type {@code boolean}, {@code byte}, {@code short}, {@code char} or {@code int}. For non-boolean
* fields, the field's value is set to {@code 0} for {@code false} or {@code 1} for {@code true}.
* </p>
* <p>
* <b>Important</b>: A default value in a Java class file defines a field's value prior to the class's initialization. This value
* is only visible to code if the field is declared {@code static}. A default value can also be set for non-static fields where
* the value is not visible to code. The Java compiler only defines such values for {@code final} fields.
* </p>
*
* @param value The value to define as a default value of the defined field.
* @return A new builder that is equal to this builder but with the given default value declared for the
* previously defined or matched field.
*/
FieldDefinition.
Optional<U>
value(boolean
value);
/**
* <p>
* Defines the supplied {@code int} value as a default value of the previously defined or matched field. The value can only
* be set for numeric fields of type {@code boolean}, {@code byte}, {@code short}, {@code char} or {@code int} where the
* value must be within the numeric type's range. The {@code boolean} type is regarded as a numeric type with the possible
* values of {@code 0} and {@code 1} representing {@code false} and {@code true}.
* </p>
* <p>
* <b>Important</b>: A default value in a Java class file defines a field's value prior to the class's initialization. This value
* is only visible to code if the field is declared {@code static}. A default value can also be set for non-static fields where
* the value is not visible to code. The Java compiler only defines such values for {@code final} fields.
* </p>
*
* @param value The value to define as a default value of the defined field.
* @return A new builder that is equal to this builder but with the given default value declared for the
* previously defined or matched field.
*/
FieldDefinition.
Optional<U>
value(int
value);
/**
* <p>
* Defines the supplied {@code long} value as a default value of the previously defined or matched field.
* </p>
* <p>
* <b>Important</b>: A default value in a Java class file defines a field's value prior to the class's initialization. This value
* is only visible to code if the field is declared {@code static}. A default value can also be set for non-static fields where
* the value is not visible to code. The Java compiler only defines such values for {@code final} fields.
* </p>
*
* @param value The value to define as a default value of the defined field.
* @return A new builder that is equal to this builder but with the given default value declared for the
* previously defined or matched field.
*/
FieldDefinition.
Optional<U>
value(long
value);
/**
* <p>
* Defines the supplied {@code float} value as a default value of the previously defined or matched field.
* </p>
* <p>
* <b>Important</b>: A default value in a Java class file defines a field's value prior to the class's initialization. This value
* is only visible to code if the field is declared {@code static}. A default value can also be set for non-static fields where
* the value is not visible to code. The Java compiler only defines such values for {@code final} fields.
* </p>
*
* @param value The value to define as a default value of the defined field.
* @return A new builder that is equal to this builder but with the given default value declared for the
* previously defined or matched field.
*/
FieldDefinition.
Optional<U>
value(float
value);
/**
* <p>
* Defines the supplied {@code double} value as a default value of the previously defined or matched field.
* </p>
* <p>
* <b>Important</b>: A default value in a Java class file defines a field's value prior to the class's initialization. This value
* is only visible to code if the field is declared {@code static}. A default value can also be set for non-static fields where
* the value is not visible to code. The Java compiler only defines such values for {@code final} fields.
* </p>
*
* @param value The value to define as a default value of the defined field.
* @return A new builder that is equal to this builder but with the given default value declared for the
* previously defined or matched field.
*/
FieldDefinition.
Optional<U>
value(double
value);
/**
* <p>
* Defines the supplied {@link String} value as a default value of the previously defined or matched field.
* </p>
* <p>
* <b>Important</b>: A default value in a Java class file defines a field's value prior to the class's initialization. This value
* is only visible to code if the field is declared {@code static}. A default value can also be set for non-static fields where
* the value is not visible to code. The Java compiler only defines such values for {@code final} fields.
* </p>
*
* @param value The value to define as a default value of the defined field.
* @return A new builder that is equal to this builder but with the given default value declared for the
* previously defined or matched field.
*/
FieldDefinition.
Optional<U>
value(
String value);
}
/**
* A builder for an optional field definition.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Optional<U> extends
FieldDefinition<U>,
Builder<U> {
/**
* A builder for an optional field definition that allows for defining a value.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Valuable<V> extends
FieldDefinition.
Valuable<V>,
Optional<V> {
/**
* An abstract base implementation of an optional field definition that allows for defining a value.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<U> extends
Optional.
AbstractBase<U> implements
Optional.
Valuable<U> {
@
Override
public
FieldDefinition.
Optional<U>
value(boolean
value) {
return
defaultValue(
value ? 1 : 0);
}
@
Override
public
FieldDefinition.
Optional<U>
value(int
value) {
return
defaultValue(
value);
}
@
Override
public
FieldDefinition.
Optional<U>
value(long
value) {
return
defaultValue(
value);
}
@
Override
public
FieldDefinition.
Optional<U>
value(float
value) {
return
defaultValue(
value);
}
@
Override
public
FieldDefinition.
Optional<U>
value(double
value) {
return
defaultValue(
value);
}
@
Override
public
FieldDefinition.
Optional<U>
value(
String value) {
if (
value == null) {
throw new
IllegalArgumentException("Cannot set null as a default value");
}
return
defaultValue(
value);
}
/**
* Defines the supplied value as a default value of the previously defined or matched field.
*
* @param defaultValue The value to define as a default value of the defined field.
* @return A new builder that is equal to this builder but with the given default value declared for the
* previously defined or matched field.
*/
protected abstract
FieldDefinition.
Optional<U>
defaultValue(
Object defaultValue);
/**
* An adapter for an optional field definition that allows for defining a value.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
@
HashCodeAndEqualsPlugin.
Enhance
private abstract static class
Adapter<V> extends
Optional.
Valuable.
AbstractBase<V> {
/**
* The field attribute appender factory to apply.
*/
protected final
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory;
/**
* The field transformer to apply.
*/
protected final
Transformer<
FieldDescription>
transformer;
/**
* The field's default value or {@code null} if no value is to be defined.
*/
@
HashCodeAndEqualsPlugin.
ValueHandling(
HashCodeAndEqualsPlugin.
ValueHandling.
Sort.
REVERSE_NULLABILITY)
protected final
Object defaultValue;
/**
* Creates a new field adapter.
*
* @param fieldAttributeAppenderFactory The field attribute appender factory to apply.
* @param transformer The field transformer to apply.
* @param defaultValue The field's default value or {@code null} if no value is to be defined.
*/
protected
Adapter(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory,
Transformer<
FieldDescription>
transformer,
Object defaultValue) {
this.
fieldAttributeAppenderFactory =
fieldAttributeAppenderFactory;
this.
transformer =
transformer;
this.
defaultValue =
defaultValue;
}
@
Override
public
FieldDefinition.
Optional<V>
attribute(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory) {
return
materialize(new
FieldAttributeAppender.
Factory.
Compound(this.
fieldAttributeAppenderFactory,
fieldAttributeAppenderFactory),
transformer,
defaultValue);
}
@
Override
@
SuppressWarnings("unchecked") // In absence of @SafeVarargs for Java 6
public
FieldDefinition.
Optional<V>
transform(
Transformer<
FieldDescription>
transformer) {
return
materialize(
fieldAttributeAppenderFactory, new
Transformer.
Compound<
FieldDescription>(this.
transformer,
transformer),
defaultValue);
}
@
Override
protected
FieldDefinition.
Optional<V>
defaultValue(
Object defaultValue) {
return
materialize(
fieldAttributeAppenderFactory,
transformer,
defaultValue);
}
/**
* Creates a new optional field definition for which all of the supplied values are represented.
*
* @param fieldAttributeAppenderFactory The field attribute appender factory to apply.
* @param transformer The field transformer to apply.
* @param defaultValue The field's default value or {@code null} if no value is to be defined.
* @return A new field definition that represents the supplied values.
*/
protected abstract
FieldDefinition.
Optional<V>
materialize(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory,
Transformer<
FieldDescription>
transformer,
Object defaultValue);
}
}
}
/**
* An abstract base implementation for an optional field definition.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<U> extends
Builder.
AbstractBase.
Delegator<U> implements
FieldDefinition.
Optional<U> {
@
Override
public
FieldDefinition.
Optional<U>
annotateField(
Annotation...
annotation) {
return
annotateField(
Arrays.
asList(
annotation));
}
@
Override
public
FieldDefinition.
Optional<U>
annotateField(
List<? extends
Annotation>
annotations) {
return
annotateField(new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
FieldDefinition.
Optional<U>
annotateField(
AnnotationDescription...
annotation) {
return
annotateField(
Arrays.
asList(
annotation));
}
}
}
}
/**
* A builder for a method definition.
*
* @param <S> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
MethodDefinition<S> extends
Builder<S> {
/**
* Annotates the previously defined or matched method with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method.
*/
MethodDefinition<S>
annotateMethod(
Annotation...
annotation);
/**
* Annotates the previously defined or matched method with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method.
*/
MethodDefinition<S>
annotateMethod(
List<? extends
Annotation>
annotations);
/**
* Annotates the previously defined or matched method with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method.
*/
MethodDefinition<S>
annotateMethod(
AnnotationDescription...
annotation);
/**
* Annotates the previously defined or matched method with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method.
*/
MethodDefinition<S>
annotateMethod(
Collection<? extends
AnnotationDescription>
annotations);
/**
* Annotates the parameter of the given index of the previously defined or matched method with the supplied annotations.
*
* @param index The parameter's index.
* @param annotation The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method's parameter of the given index.
*/
MethodDefinition<S>
annotateParameter(int
index,
Annotation...
annotation);
/**
* Annotates the parameter of the given index of the previously defined or matched method with the supplied annotations.
*
* @param index The parameter's index.
* @param annotations The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method's parameter of the given index.
*/
MethodDefinition<S>
annotateParameter(int
index,
List<? extends
Annotation>
annotations);
/**
* Annotates the parameter of the given index of the previously defined or matched method with the supplied annotations.
*
* @param index The parameter's index.
* @param annotation The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method's parameter of the given index.
*/
MethodDefinition<S>
annotateParameter(int
index,
AnnotationDescription...
annotation);
/**
* Annotates the parameter of the given index of the previously defined or matched method with the supplied annotations.
*
* @param index The parameter's index.
* @param annotations The annotations to declare on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined or matched method's parameter of the given index.
*/
MethodDefinition<S>
annotateParameter(int
index,
Collection<? extends
AnnotationDescription>
annotations);
/**
* Applies the supplied method attribute appender factory onto the previously defined or matched method.
*
* @param methodAttributeAppenderFactory The method attribute appender factory that should be applied on the
* previously defined or matched method.
* @return A new builder that is equal to this builder but with the supplied method attribute appender factory
* applied to the previously defined or matched method.
*/
MethodDefinition<S>
attribute(
MethodAttributeAppender.
Factory methodAttributeAppenderFactory);
/**
* Applies the supplied transformer onto the previously defined or matched method. The transformed
* method is written <i>as it is</i> and it not subject to any validations.
*
* @param transformer The transformer to apply to the previously defined or matched method.
* @return A new builder that is equal to this builder but with the supplied transformer
* applied to the previously defined or matched method.
*/
MethodDefinition<S>
transform(
Transformer<
MethodDescription>
transformer);
/**
* A builder for a method definition with a receiver type.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
ReceiverTypeDefinition<U> extends
MethodDefinition<U> {
/**
* Defines the supplied (annotated) receiver type for the previously defined or matched method.
*
* @param receiverType The receiver type to define on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given type defined as the
* receiver on the previously defined or matched method.
*/
MethodDefinition<U>
receiverType(
AnnotatedElement receiverType);
/**
* Defines the supplied (annotated) receiver type for the previously defined or matched method.
*
* @param receiverType The receiver type to define on the previously defined or matched method.
* @return A new builder that is equal to this builder but with the given type defined as the
* receiver on the previously defined or matched method.
*/
MethodDefinition<U>
receiverType(
TypeDescription.
Generic receiverType);
/**
* An abstract base implementation of a method definition that can accept a receiver type.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<V> extends
MethodDefinition.
AbstractBase<V> implements
ReceiverTypeDefinition<V> {
@
Override
public
MethodDefinition<V>
receiverType(
AnnotatedElement receiverType) {
return
receiverType(
TypeDescription.
Generic.
AnnotationReader.
DISPATCHER.
resolve(
receiverType));
}
}
}
/**
* A builder for defining an implementation of a method.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
ImplementationDefinition<U> {
/**
* Implements the previously defined or matched method by the supplied implementation. A method interception
* is typically implemented in one of the following ways:
* <ol>
* <li>If a method is declared by the instrumented type and the type builder creates a subclass or redefinition,
* any preexisting method is replaced by the given implementation. Any previously defined implementation is lost.</li>
* <li>If a method is declared by the instrumented type and the type builder creates a rebased version of the
* instrumented type, the original method is preserved within a private, synthetic method within the instrumented
* type. The original method therefore remains invokeable and is treated as the direct super method of the new
* method. When rebasing a type, it therefore becomes possible to invoke a non-virtual method's super method
* when a preexisting method body is replaced.</li>
* <li>If a virtual method is inherited from a super type, it is overridden. The overridden method is available
* for super method invocation.</li>
* </ol>
*
* @param implementation The implementation for implementing the previously defined or matched method.
* @return A new builder where the previously defined or matched method is implemented by the
* supplied implementation.
*/
MethodDefinition.
ReceiverTypeDefinition<U>
intercept(
Implementation implementation);
/**
* Defines the previously defined or matched method to be {@code abstract}.
*
* @return A new builder where the previously defined or matched method is implemented to be abstract.
*/
MethodDefinition.
ReceiverTypeDefinition<U>
withoutCode();
/**
* Defines the previously defined or matched method to return the supplied value as an annotation default value. The
* value must be supplied in its unloaded state, i.e. enumerations as {@link net.bytebuddy.description.enumeration.EnumerationDescription},
* types as {@link TypeDescription} and annotations as {@link AnnotationDescription}. For supplying loaded types, use
* {@link ImplementationDefinition#defaultValue(Object, Class)} must be used.
*
* @param annotationValue The value to be defined as a default value.
* @return A builder where the previously defined or matched method is implemented to return an annotation default value.
*/
MethodDefinition.
ReceiverTypeDefinition<U>
defaultValue(
AnnotationValue<?, ?>
annotationValue);
/**
* Defines the previously defined or matched method to return the supplied value as an annotation default value. The
* value must be supplied in its loaded state paired with the property type of the value.
*
* @param value The value to be defined as a default value.
* @param type The type of the annotation property.
* @param <W> The type of the annotation property.
* @return A builder where the previously defined or matched method is implemented to return an annotation default value.
*/
<W>
MethodDefinition.
ReceiverTypeDefinition<U>
defaultValue(W
value,
Class<? extends W>
type);
/**
* A builder for optionally defining an implementation of a method.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Optional<V> extends
ImplementationDefinition<V>,
Builder<V> {
/* union type */
}
/**
* An abstract base implementation for a builder optionally defining an implementation of a method.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<V> implements
ImplementationDefinition<V> {
@
Override
public <W>
MethodDefinition.
ReceiverTypeDefinition<V>
defaultValue(W
value,
Class<? extends W>
type) {
return
defaultValue(
AnnotationDescription.
ForLoadedAnnotation.
asValue(
value,
type));
}
}
}
/**
* A builder for defining an implementation of a method and optionally defining a type variable.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
TypeVariableDefinition<U> extends
ImplementationDefinition<U> {
/**
* Defines a method variable to be declared by the currently defined method. The defined method variable does not define any bounds.
*
* @param symbol The symbol of the type variable.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified type variable.
*/
Annotatable<U>
typeVariable(
String symbol);
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param symbol The symbol of the type variable.
* @param bound The bounds of the type variables. Can also be {@link net.bytebuddy.dynamic.TargetType} for any type
* if a bound type should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified type variable.
*/
Annotatable<U>
typeVariable(
String symbol,
Type...
bound);
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param symbol The symbol of the type variable.
* @param bounds The bounds of the type variables. Can also be {@link net.bytebuddy.dynamic.TargetType} for any type
* if a bound type should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified type variable.
*/
Annotatable<U>
typeVariable(
String symbol,
List<? extends
Type>
bounds);
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param symbol The symbol of the type variable.
* @param bound The bounds of the type variables. Can also be {@link net.bytebuddy.dynamic.TargetType} for any type
* if a bound type should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified type variable.
*/
Annotatable<U>
typeVariable(
String symbol,
TypeDefinition...
bound);
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param symbol The symbol of the type variable.
* @param bounds The bounds of the type variables. Can also be {@link net.bytebuddy.dynamic.TargetType} for any type
* if a bound type should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified type variable.
*/
Annotatable<U>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds);
/**
* A builder for optionally defining an annotation for a type variable.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Annotatable<V> extends
TypeVariableDefinition<V> {
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
Annotatable<V>
annotateTypeVariable(
Annotation...
annotation);
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
Annotatable<V>
annotateTypeVariable(
List<? extends
Annotation>
annotations);
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotation The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
Annotatable<V>
annotateTypeVariable(
AnnotationDescription...
annotation);
/**
* Annotates the previously defined type variable with the supplied annotations.
*
* @param annotations The annotations to declare on the previously defined type variable.
* @return A new builder that is equal to this builder but with the given annotations declared
* on the previously defined type variable.
*/
Annotatable<V>
annotateTypeVariable(
Collection<? extends
AnnotationDescription>
annotations);
/**
* An abstract base implementation for defining an annotation on a parameter.
*
* @param <W> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<W> extends
TypeVariableDefinition.
AbstractBase<W> implements
Annotatable<W> {
@
Override
public
TypeVariableDefinition.
Annotatable<W>
annotateTypeVariable(
Annotation...
annotation) {
return
annotateTypeVariable(
Arrays.
asList(
annotation));
}
@
Override
public
TypeVariableDefinition.
Annotatable<W>
annotateTypeVariable(
List<? extends
Annotation>
annotations) {
return
annotateTypeVariable(new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
TypeVariableDefinition.
Annotatable<W>
annotateTypeVariable(
AnnotationDescription...
annotation) {
return
annotateTypeVariable(
Arrays.
asList(
annotation));
}
/**
* An adapter implementation for an annotatable type variable definition.
*
* @param <X> A loaded type that the built type is guaranteed to be a subclass of.
*/
protected abstract static class
Adapter<X> extends
TypeVariableDefinition.
Annotatable.
AbstractBase<X> {
@
Override
public
TypeVariableDefinition.
Annotatable<X>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds) {
return
materialize().
typeVariable(
symbol,
bounds);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
intercept(
Implementation implementation) {
return
materialize().
intercept(
implementation);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
withoutCode() {
return
materialize().
withoutCode();
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
defaultValue(
AnnotationValue<?, ?>
annotationValue) {
return
materialize().
defaultValue(
annotationValue);
}
@
Override
public <V>
MethodDefinition.
ReceiverTypeDefinition<X>
defaultValue(V
value,
Class<? extends V>
type) {
return
materialize().
defaultValue(
value,
type);
}
/**
* Materializes this instance as a parameter definition with the currently defined properties.
*
* @return A parameter definition with the currently defined properties.
*/
protected abstract
MethodDefinition.
ParameterDefinition<X>
materialize();
}
}
}
/**
* An abstract base implementation for defining an implementation of a method and optionally defining a type variable.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<V> extends
ImplementationDefinition.
AbstractBase<V> implements
TypeVariableDefinition<V> {
@
Override
public
Annotatable<V>
typeVariable(
String symbol) {
return
typeVariable(
symbol,
Collections.
singletonList(
Object.class));
}
@
Override
public
Annotatable<V>
typeVariable(
String symbol,
Type...
bound) {
return
typeVariable(
symbol,
Arrays.
asList(
bound));
}
@
Override
public
Annotatable<V>
typeVariable(
String symbol,
List<? extends
Type>
bounds) {
return
typeVariable(
symbol, new
TypeList.
Generic.
ForLoadedTypes(
bounds));
}
@
Override
public
Annotatable<V>
typeVariable(
String symbol,
TypeDefinition...
bound) {
return
typeVariable(
symbol,
Arrays.
asList(
bound));
}
}
}
/**
* A builder for defining an implementation of a method and optionally defining a type variable or thrown exception.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
ExceptionDefinition<U> extends
TypeVariableDefinition<U> {
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param type The type of the exception being declared by the currently defined method.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified exception type.
*/
ExceptionDefinition<U>
throwing(
Type...
type);
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param types The type of the exception being declared by the currently defined method.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified exception type.
*/
ExceptionDefinition<U>
throwing(
List<? extends
Type>
types);
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param type The type of the exception being declared by the currently defined method.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified exception type.
*/
ExceptionDefinition<U>
throwing(
TypeDefinition...
type);
/**
* Defines a method variable to be declared by the currently defined method.
*
* @param types The type of the exception being declared by the currently defined method.
* @return A new builder that is equal to the current builder but where the currently defined method declares the specified exception type.
*/
ExceptionDefinition<U>
throwing(
Collection<? extends
TypeDefinition>
types);
/**
* An abstract base implementation for defining an implementation of a method and optionally defining a type variable or thrown exception.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<V> extends
TypeVariableDefinition.
AbstractBase<V> implements
ExceptionDefinition<V> {
@
Override
public
ExceptionDefinition<V>
throwing(
Type...
type) {
return
throwing(
Arrays.
asList(
type));
}
@
Override
public
ExceptionDefinition<V>
throwing(
List<? extends
Type>
types) {
return
throwing(new
TypeList.
Generic.
ForLoadedTypes(
types));
}
@
Override
public
ExceptionDefinition<V>
throwing(
TypeDefinition...
type) {
return
throwing(
Arrays.
asList(
type));
}
}
}
/**
* A builder for defining an implementation of a method and optionally defining a type variable, thrown exception or method parameter.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
ParameterDefinition<U> extends
ExceptionDefinition<U> {
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @param name The parameter's name.
* @param modifierContributor The parameter's modifiers.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<U>
withParameter(
Type type,
String name,
ModifierContributor.
ForParameter...
modifierContributor);
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @param name The parameter's name.
* @param modifierContributors The parameter's modifiers.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<U>
withParameter(
Type type,
String name,
Collection<? extends
ModifierContributor.
ForParameter>
modifierContributors);
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @param name The parameter's name.
* @param modifiers The parameter's modifiers.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<U>
withParameter(
Type type,
String name, int
modifiers);
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @param name The parameter's name.
* @param modifierContributor The parameter's modifiers.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<U>
withParameter(
TypeDefinition type,
String name,
ModifierContributor.
ForParameter...
modifierContributor);
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @param name The parameter's name.
* @param modifierContributors The parameter's modifiers.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<U>
withParameter(
TypeDefinition type,
String name,
Collection<? extends
ModifierContributor.
ForParameter>
modifierContributors);
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @param name The parameter's name.
* @param modifiers The parameter's modifiers.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<U>
withParameter(
TypeDefinition type,
String name, int
modifiers);
/**
* A builder for optionally defining an annotation on a parameter.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Annotatable<V> extends
ParameterDefinition<V> {
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotation The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
Annotation...
annotation);
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotations The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
List<? extends
Annotation>
annotations);
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotation The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
AnnotationDescription...
annotation);
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotations The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
Collection<? extends
AnnotationDescription>
annotations);
/**
* An abstract base implementation for defining an annotation on a parameter.
*
* @param <W> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<W> extends
ParameterDefinition.
AbstractBase<W> implements
Annotatable<W> {
@
Override
public
ParameterDefinition.
Annotatable<W>
annotateParameter(
Annotation...
annotation) {
return
annotateParameter(
Arrays.
asList(
annotation));
}
@
Override
public
ParameterDefinition.
Annotatable<W>
annotateParameter(
List<? extends
Annotation>
annotations) {
return
annotateParameter(new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
ParameterDefinition.
Annotatable<W>
annotateParameter(
AnnotationDescription...
annotation) {
return
annotateParameter(
Arrays.
asList(
annotation));
}
/**
* An adapter implementation for defining an annotation on a parameter.
*
* @param <X> A loaded type that the built type is guaranteed to be a subclass of.
*/
protected abstract static class
Adapter<X> extends
ParameterDefinition.
Annotatable.
AbstractBase<X> {
@
Override
public
ParameterDefinition.
Annotatable<X>
withParameter(
TypeDefinition type,
String name, int
modifiers) {
return
materialize().
withParameter(
type,
name,
modifiers);
}
@
Override
public
ExceptionDefinition<X>
throwing(
Collection<? extends
TypeDefinition>
types) {
return
materialize().
throwing(
types);
}
@
Override
public
TypeVariableDefinition.
Annotatable<X>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds) {
return
materialize().
typeVariable(
symbol,
bounds);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
intercept(
Implementation implementation) {
return
materialize().
intercept(
implementation);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
withoutCode() {
return
materialize().
withoutCode();
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
defaultValue(
AnnotationValue<?, ?>
annotationValue) {
return
materialize().
defaultValue(
annotationValue);
}
@
Override
public <V>
MethodDefinition.
ReceiverTypeDefinition<X>
defaultValue(V
value,
Class<? extends V>
type) {
return
materialize().
defaultValue(
value,
type);
}
/**
* Materializes this instance as a parameter definition with the currently defined properties.
*
* @return A parameter definition with the currently defined properties.
*/
protected abstract
MethodDefinition.
ParameterDefinition<X>
materialize();
}
}
}
/**
* A builder for defining an implementation of a method and optionally defining a type variable, thrown exception or a parameter type.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Simple<V> extends
ExceptionDefinition<V> {
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<V>
withParameter(
Type type);
/**
* Defines the specified parameter for the currently defined method as the last parameter of the currently defined method.
*
* @param type The parameter's type. Can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameter.
*/
Annotatable<V>
withParameter(
TypeDefinition type);
/**
* A builder for optionally defining an annotation on a parameter.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Annotatable<V> extends
Simple<V> {
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotation The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
Annotation...
annotation);
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotations The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
List<? extends
Annotation>
annotations);
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotation The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
AnnotationDescription...
annotation);
/**
* Annotates the previously defined parameter with the specified annotations.
*
* @param annotations The annotations to declare on the previously defined parameter.
* @return A new builder that is equal to this builder but with the previously defined parameter annotated with
* the specified annotations.
*/
Annotatable<V>
annotateParameter(
Collection<? extends
AnnotationDescription>
annotations);
/**
* An abstract base implementation of a simple parameter definition.
*
* @param <W> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<W> extends
Simple.
AbstractBase<W> implements
Annotatable<W> {
@
Override
public
Simple.
Annotatable<W>
annotateParameter(
Annotation...
annotation) {
return
annotateParameter(
Arrays.
asList(
annotation));
}
@
Override
public
Simple.
Annotatable<W>
annotateParameter(
List<? extends
Annotation>
annotations) {
return
annotateParameter(new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
Simple.
Annotatable<W>
annotateParameter(
AnnotationDescription...
annotation) {
return
annotateParameter(
Arrays.
asList(
annotation));
}
/**
* An adapter implementation of a simple parameter definition.
*
* @param <X> A loaded type that the built type is guaranteed to be a subclass of.
*/
protected abstract static class
Adapter<X> extends
Simple.
Annotatable.
AbstractBase<X> {
@
Override
public
Simple.
Annotatable<X>
withParameter(
TypeDefinition type) {
return
materialize().
withParameter(
type);
}
@
Override
public
ExceptionDefinition<X>
throwing(
Collection<? extends
TypeDefinition>
types) {
return
materialize().
throwing(
types);
}
@
Override
public
TypeVariableDefinition.
Annotatable<X>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds) {
return
materialize().
typeVariable(
symbol,
bounds);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
intercept(
Implementation implementation) {
return
materialize().
intercept(
implementation);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
withoutCode() {
return
materialize().
withoutCode();
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<X>
defaultValue(
AnnotationValue<?, ?>
annotationValue) {
return
materialize().
defaultValue(
annotationValue);
}
@
Override
public <V>
MethodDefinition.
ReceiverTypeDefinition<X>
defaultValue(V
value,
Class<? extends V>
type) {
return
materialize().
defaultValue(
value,
type);
}
/**
* Materializes this instance as a simple parameter definition with the currently defined properties.
*
* @return A simple parameter definition with the currently defined properties.
*/
protected abstract
MethodDefinition.
ParameterDefinition.
Simple<X>
materialize();
}
}
}
/**
* An abstract base implementation of an exception definition.
*
* @param <W> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<W> extends
ExceptionDefinition.
AbstractBase<W> implements
Simple<W> {
@
Override
public
Simple.
Annotatable<W>
withParameter(
Type type) {
return
withParameter(
TypeDefinition.
Sort.
describe(
type));
}
}
}
/**
* A builder for defining an implementation of a method and optionally defining a type variable, thrown exception or method parameter.
* Implementations allow for the <i>one-by-one</i> definition of parameters what gives opportunity to annotate parameters in a fluent
* style. Doing so, it is optionally possible to define parameter names and modifiers. This can be done for either all or no parameters.
* Alternatively, parameters without annotations, names or modifiers can be defined by a single step.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
interface
Initial<V> extends
ParameterDefinition<V>,
Simple<V> {
/**
* Defines the specified parameters for the currently defined method.
*
* @param type The parameter types. Any type can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameters.
*/
ExceptionDefinition<V>
withParameters(
Type...
type);
/**
* Defines the specified parameters for the currently defined method.
*
* @param types The parameter types. Any type can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameters.
*/
ExceptionDefinition<V>
withParameters(
List<? extends
Type>
types);
/**
* Defines the specified parameters for the currently defined method.
*
* @param type The parameter types. Any type can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameters.
*/
ExceptionDefinition<V>
withParameters(
TypeDefinition...
type);
/**
* Defines the specified parameters for the currently defined method.
*
* @param types The parameter types. Any type can also be {@link net.bytebuddy.dynamic.TargetType} if the parameter type
* should be equal to the currently instrumented type.
* @return A new builder that is equal to the current builder but where the currently defined method appends the specified parameters.
*/
ExceptionDefinition<V>
withParameters(
Collection<? extends
TypeDefinition>
types);
/**
* An abstract base implementation for an initial parameter definition.
*
* @param <W> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<W> extends
ParameterDefinition.
AbstractBase<W> implements
Initial<W> {
@
Override
public
Simple.
Annotatable<W>
withParameter(
Type type) {
return
withParameter(
TypeDefinition.
Sort.
describe(
type));
}
@
Override
public
ExceptionDefinition<W>
withParameters(
Type...
type) {
return
withParameters(
Arrays.
asList(
type));
}
@
Override
public
ExceptionDefinition<W>
withParameters(
List<? extends
Type>
types) {
return
withParameters(new
TypeList.
Generic.
ForLoadedTypes(
types));
}
@
Override
public
ExceptionDefinition<W>
withParameters(
TypeDefinition...
type) {
return
withParameters(
Arrays.
asList(
type));
}
@
Override
public
ExceptionDefinition<W>
withParameters(
Collection<? extends
TypeDefinition>
types) {
ParameterDefinition.
Simple<W>
parameterDefinition = this;
for (
TypeDefinition type :
types) {
parameterDefinition =
parameterDefinition.
withParameter(
type);
}
return
parameterDefinition;
}
}
}
/**
* An abstract base implementation for defining an implementation of a method and optionally defining a type variable, thrown exception or parameter type.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<V> extends
ExceptionDefinition.
AbstractBase<V> implements
ParameterDefinition<V> {
@
Override
public
ParameterDefinition.
Annotatable<V>
withParameter(
Type type,
String name,
ModifierContributor.
ForParameter...
modifierContributor) {
return
withParameter(
type,
name,
Arrays.
asList(
modifierContributor));
}
@
Override
public
ParameterDefinition.
Annotatable<V>
withParameter(
Type type,
String name,
Collection<? extends
ModifierContributor.
ForParameter>
modifierContributors) {
return
withParameter(
type,
name,
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
@
Override
public
ParameterDefinition.
Annotatable<V>
withParameter(
Type type,
String name, int
modifiers) {
return
withParameter(
TypeDefinition.
Sort.
describe(
type),
name,
modifiers);
}
@
Override
public
ParameterDefinition.
Annotatable<V>
withParameter(
TypeDefinition type,
String name,
ModifierContributor.
ForParameter...
modifierContributor) {
return
withParameter(
type,
name,
Arrays.
asList(
modifierContributor));
}
@
Override
public
ParameterDefinition.
Annotatable<V>
withParameter(
TypeDefinition type,
String name,
Collection<? extends
ModifierContributor.
ForParameter>
modifierContributors) {
return
withParameter(
type,
name,
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
}
}
/**
* An abstract base implementation of a method definition.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<U> extends
Builder.
AbstractBase.
Delegator<U> implements
MethodDefinition<U> {
@
Override
public
MethodDefinition<U>
annotateMethod(
Annotation...
annotation) {
return
annotateMethod(
Arrays.
asList(
annotation));
}
@
Override
public
MethodDefinition<U>
annotateMethod(
List<? extends
Annotation>
annotations) {
return
annotateMethod(new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
MethodDefinition<U>
annotateMethod(
AnnotationDescription...
annotation) {
return
annotateMethod(
Arrays.
asList(
annotation));
}
@
Override
public
MethodDefinition<U>
annotateParameter(int
index,
Annotation...
annotation) {
return
annotateParameter(
index,
Arrays.
asList(
annotation));
}
@
Override
public
MethodDefinition<U>
annotateParameter(int
index,
List<? extends
Annotation>
annotations) {
return
annotateParameter(
index, new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
MethodDefinition<U>
annotateParameter(int
index,
AnnotationDescription...
annotation) {
return
annotateParameter(
index,
Arrays.
asList(
annotation));
}
/**
* An adapter implementation of a method definition.
*
* @param <V> A loaded type that the built type is guaranteed to be a subclass of.
*/
@
HashCodeAndEqualsPlugin.
Enhance
protected abstract static class
Adapter<V> extends
MethodDefinition.
ReceiverTypeDefinition.
AbstractBase<V> {
/**
* The handler that determines how a method is implemented.
*/
protected final
MethodRegistry.
Handler handler;
/**
* The method attribute appender factory to apply onto the method that is currently being implemented.
*/
protected final
MethodAttributeAppender.
Factory methodAttributeAppenderFactory;
/**
* The transformer to apply onto the method that is currently being implemented.
*/
protected final
Transformer<
MethodDescription>
transformer;
/**
* Creates a new adapter for a method definition.
*
* @param handler The handler that determines how a method is implemented.
* @param methodAttributeAppenderFactory The method attribute appender factory to apply onto the method that is currently being implemented.
* @param transformer The transformer to apply onto the method that is currently being implemented.
*/
protected
Adapter(
MethodRegistry.
Handler handler,
MethodAttributeAppender.
Factory methodAttributeAppenderFactory,
Transformer<
MethodDescription>
transformer) {
this.
handler =
handler;
this.
methodAttributeAppenderFactory =
methodAttributeAppenderFactory;
this.
transformer =
transformer;
}
@
Override
public
MethodDefinition<V>
attribute(
MethodAttributeAppender.
Factory methodAttributeAppenderFactory) {
return
materialize(
handler, new
MethodAttributeAppender.
Factory.
Compound(this.
methodAttributeAppenderFactory,
methodAttributeAppenderFactory),
transformer);
}
@
Override
@
SuppressWarnings("unchecked") // In absence of @SafeVarargs for Java 6
public
MethodDefinition<V>
transform(
Transformer<
MethodDescription>
transformer) {
return
materialize(
handler,
methodAttributeAppenderFactory, new
Transformer.
Compound<
MethodDescription>(this.
transformer,
transformer));
}
/**
* Materializes the current builder as a method definition.
*
* @param handler The handler that determines how a method is implemented.
* @param methodAttributeAppenderFactory The method attribute appender factory to apply onto the method that is currently being implemented.
* @param transformer The method transformer to apply onto the method that is currently being implemented.
* @return Returns a method definition for the supplied properties.
*/
protected abstract
MethodDefinition<V>
materialize(
MethodRegistry.
Handler handler,
MethodAttributeAppender.
Factory methodAttributeAppenderFactory,
Transformer<
MethodDescription>
transformer);
}
}
}
/**
* An abstract base implementation of a dynamic type builder.
*
* @param <S> A loaded type that the built type is guaranteed to be a subclass of.
*/
abstract class
AbstractBase<S> implements
Builder<S> {
@
Override
public
InnerTypeDefinition.
ForType<S>
innerTypeOf(
Class<?>
type) {
return
innerTypeOf(
TypeDescription.
ForLoadedType.
of(
type));
}
@
Override
public
InnerTypeDefinition<S>
innerTypeOf(
Method method) {
return
innerTypeOf(new
MethodDescription.
ForLoadedMethod(
method));
}
@
Override
public
InnerTypeDefinition<S>
innerTypeOf(
Constructor<?>
constructor) {
return
innerTypeOf(new
MethodDescription.
ForLoadedConstructor(
constructor));
}
@
Override
public
Builder<S>
declaredTypes(
Class<?>...
type) {
return
declaredTypes(
Arrays.
asList(
type));
}
@
Override
public
Builder<S>
declaredTypes(
TypeDescription...
type) {
return
declaredTypes(
Arrays.
asList(
type));
}
@
Override
public
Builder<S>
declaredTypes(
List<? extends
Class<?>>
type) {
return
declaredTypes(new
TypeList.
ForLoadedTypes(
type));
}
@
Override
public
Builder<S>
noNestMate() {
return
nestHost(
TargetType.
DESCRIPTION);
}
@
Override
public
Builder<S>
nestHost(
Class<?>
type) {
return
nestHost(
TypeDescription.
ForLoadedType.
of(
type));
}
@
Override
public
Builder<S>
nestMembers(
Class<?>...
type) {
return
nestMembers(
Arrays.
asList(
type));
}
@
Override
public
Builder<S>
nestMembers(
TypeDescription...
type) {
return
nestMembers(
Arrays.
asList(
type));
}
@
Override
public
Builder<S>
nestMembers(
List<? extends
Class<?>>
types) {
return
nestMembers(new
TypeList.
ForLoadedTypes(
types));
}
@
Override
public
Builder<S>
annotateType(
Annotation...
annotation) {
return
annotateType(
Arrays.
asList(
annotation));
}
@
Override
public
Builder<S>
annotateType(
List<? extends
Annotation>
annotations) {
return
annotateType(new
AnnotationList.
ForLoadedAnnotations(
annotations));
}
@
Override
public
Builder<S>
annotateType(
AnnotationDescription...
annotation) {
return
annotateType(
Arrays.
asList(
annotation));
}
@
Override
public
Builder<S>
modifiers(
ModifierContributor.
ForType...
modifierContributor) {
return
modifiers(
Arrays.
asList(
modifierContributor));
}
@
Override
public
Builder<S>
modifiers(
Collection<? extends
ModifierContributor.
ForType>
modifierContributors) {
return
modifiers(
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
@
Override
public
Builder<S>
merge(
ModifierContributor.
ForType...
modifierContributor) {
return
merge(
Arrays.
asList(
modifierContributor));
}
@
Override
public
MethodDefinition.
ImplementationDefinition.
Optional<S>
implement(
Type...
interfaceType) {
return
implement(
Arrays.
asList(
interfaceType));
}
@
Override
public
MethodDefinition.
ImplementationDefinition.
Optional<S>
implement(
List<? extends
Type>
interfaceTypes) {
return
implement(new
TypeList.
Generic.
ForLoadedTypes(
interfaceTypes));
}
@
Override
public
MethodDefinition.
ImplementationDefinition.
Optional<S>
implement(
TypeDefinition...
interfaceType) {
return
implement(
Arrays.
asList(
interfaceType));
}
@
Override
public
TypeVariableDefinition<S>
typeVariable(
String symbol) {
return
typeVariable(
symbol,
TypeDescription.
Generic.
OBJECT);
}
@
Override
public
TypeVariableDefinition<S>
typeVariable(
String symbol,
Type...
bound) {
return
typeVariable(
symbol,
Arrays.
asList(
bound));
}
@
Override
public
TypeVariableDefinition<S>
typeVariable(
String symbol,
List<? extends
Type>
bounds) {
return
typeVariable(
symbol, new
TypeList.
Generic.
ForLoadedTypes(
bounds));
}
@
Override
public
TypeVariableDefinition<S>
typeVariable(
String symbol,
TypeDefinition...
bound) {
return
typeVariable(
symbol,
Arrays.
asList(
bound));
}
@
Override
public
FieldDefinition.
Optional.
Valuable<S>
defineField(
String name,
Type type,
ModifierContributor.
ForField...
modifierContributor) {
return
defineField(
name,
type,
Arrays.
asList(
modifierContributor));
}
@
Override
public
FieldDefinition.
Optional.
Valuable<S>
defineField(
String name,
Type type,
Collection<? extends
ModifierContributor.
ForField>
modifierContributors) {
return
defineField(
name,
type,
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
@
Override
public
FieldDefinition.
Optional.
Valuable<S>
defineField(
String name,
Type type, int
modifiers) {
return
defineField(
name,
TypeDefinition.
Sort.
describe(
type),
modifiers);
}
@
Override
public
FieldDefinition.
Optional.
Valuable<S>
defineField(
String name,
TypeDefinition type,
ModifierContributor.
ForField...
modifierContributor) {
return
defineField(
name,
type,
Arrays.
asList(
modifierContributor));
}
@
Override
public
FieldDefinition.
Optional.
Valuable<S>
defineField(
String name,
TypeDefinition type,
Collection<? extends
ModifierContributor.
ForField>
modifierContributors) {
return
defineField(
name,
type,
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
@
Override
public
FieldDefinition.
Optional.
Valuable<S>
define(
Field field) {
return
define(new
FieldDescription.
ForLoadedField(
field));
}
@
Override
public
FieldDefinition.
Optional.
Valuable<S>
define(
FieldDescription field) {
return
defineField(
field.
getName(),
field.
getType(),
field.
getModifiers());
}
@
Override
public
FieldDefinition.
Optional<S>
serialVersionUid(long
serialVersionUid) {
return
defineField("serialVersionUID", long.class,
Visibility.
PRIVATE,
FieldManifestation.
FINAL,
Ownership.
STATIC).
value(
serialVersionUid);
}
@
Override
public
FieldDefinition.
Valuable<S>
field(
ElementMatcher<? super
FieldDescription>
matcher) {
return
field(new
LatentMatcher.
Resolved<
FieldDescription>(
matcher));
}
@
Override
public
Builder<S>
ignoreAlso(
ElementMatcher<? super
MethodDescription>
ignoredMethods) {
return
ignoreAlso(new
LatentMatcher.
Resolved<
MethodDescription>(
ignoredMethods));
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<S>
defineMethod(
String name,
Type returnType,
ModifierContributor.
ForMethod...
modifierContributor) {
return
defineMethod(
name,
returnType,
Arrays.
asList(
modifierContributor));
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<S>
defineMethod(
String name,
Type returnType,
Collection<? extends
ModifierContributor.
ForMethod>
modifierContributors) {
return
defineMethod(
name,
returnType,
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<S>
defineMethod(
String name,
Type returnType, int
modifiers) {
return
defineMethod(
name,
TypeDefinition.
Sort.
describe(
returnType),
modifiers);
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<S>
defineMethod(
String name,
TypeDefinition returnType,
ModifierContributor.
ForMethod...
modifierContributor) {
return
defineMethod(
name,
returnType,
Arrays.
asList(
modifierContributor));
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<S>
defineMethod(
String name,
TypeDefinition returnType,
Collection<? extends
ModifierContributor.
ForMethod>
modifierContributors) {
return
defineMethod(
name,
returnType,
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<S>
defineConstructor(
ModifierContributor.
ForMethod...
modifierContributor) {
return
defineConstructor(
Arrays.
asList(
modifierContributor));
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<S>
defineConstructor(
Collection<? extends
ModifierContributor.
ForMethod>
modifierContributors) {
return
defineConstructor(
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve());
}
@
Override
public
MethodDefinition.
ImplementationDefinition<S>
define(
Method method) {
return
define(new
MethodDescription.
ForLoadedMethod(
method));
}
@
Override
public
MethodDefinition.
ImplementationDefinition<S>
define(
Constructor<?>
constructor) {
return
define(new
MethodDescription.
ForLoadedConstructor(
constructor));
}
@
Override
public
MethodDefinition.
ImplementationDefinition<S>
define(
MethodDescription methodDescription) {
MethodDefinition.
ParameterDefinition.
Initial<S>
initialParameterDefinition =
methodDescription.
isConstructor()
?
defineConstructor(
methodDescription.
getModifiers())
:
defineMethod(
methodDescription.
getInternalName(),
methodDescription.
getReturnType(),
methodDescription.
getModifiers());
ParameterList<?>
parameterList =
methodDescription.
getParameters();
MethodDefinition.
ExceptionDefinition<S>
exceptionDefinition;
if (
parameterList.
hasExplicitMetaData()) {
MethodDefinition.
ParameterDefinition<S>
parameterDefinition =
initialParameterDefinition;
for (
ParameterDescription parameter :
parameterList) {
parameterDefinition =
parameterDefinition.
withParameter(
parameter.
getType(),
parameter.
getName(),
parameter.
getModifiers());
}
exceptionDefinition =
parameterDefinition;
} else {
exceptionDefinition =
initialParameterDefinition.
withParameters(
parameterList.
asTypeList());
}
MethodDefinition.
TypeVariableDefinition<S>
typeVariableDefinition =
exceptionDefinition.
throwing(
methodDescription.
getExceptionTypes());
for (
TypeDescription.
Generic typeVariable :
methodDescription.
getTypeVariables()) {
typeVariableDefinition =
typeVariableDefinition.
typeVariable(
typeVariable.
getSymbol(),
typeVariable.
getUpperBounds());
}
return
typeVariableDefinition;
}
@
Override
public
FieldDefinition.
Optional<S>
defineProperty(
String name,
Type type) {
return
defineProperty(
name,
TypeDefinition.
Sort.
describe(
type));
}
@
Override
public
FieldDefinition.
Optional<S>
defineProperty(
String name,
Type type, boolean
readOnly) {
return
defineProperty(
name,
TypeDefinition.
Sort.
describe(
type),
readOnly);
}
@
Override
public
FieldDefinition.
Optional<S>
defineProperty(
String name,
TypeDefinition type) {
return
defineProperty(
name,
type, false);
}
@
Override
public
FieldDefinition.
Optional<S>
defineProperty(
String name,
TypeDefinition type, boolean
readOnly) {
if (
name.
isEmpty()) {
throw new
IllegalArgumentException("A bean property cannot have an empty name");
} else if (
type.
represents(void.class)) {
throw new
IllegalArgumentException("A bean property cannot have a void type");
}
DynamicType.
Builder<S>
builder = this;
FieldManifestation fieldManifestation;
if (!
readOnly) {
builder =
builder
.
defineMethod("set" +
Character.
toUpperCase(
name.
charAt(0)) +
name.
substring(1), void.class,
Visibility.
PUBLIC)
.
withParameters(
type)
.
intercept(
FieldAccessor.
ofField(
name));
fieldManifestation =
FieldManifestation.
PLAIN;
} else {
fieldManifestation =
FieldManifestation.
FINAL;
}
return
builder
.
defineMethod((
type.
represents(boolean.class) ||
type.
represents(
Boolean.class)
? "is"
: "get") +
Character.
toUpperCase(
name.
charAt(0)) +
name.
substring(1),
type,
Visibility.
PUBLIC)
.
intercept(
FieldAccessor.
ofField(
name))
.
defineField(
name,
type,
Visibility.
PRIVATE,
fieldManifestation);
}
@
Override
public
MethodDefinition.
ImplementationDefinition<S>
method(
ElementMatcher<? super
MethodDescription>
matcher) {
return
invokable(
isMethod().
and(
matcher));
}
@
Override
public
MethodDefinition.
ImplementationDefinition<S>
constructor(
ElementMatcher<? super
MethodDescription>
matcher) {
return
invokable(
isConstructor().
and(
matcher));
}
@
Override
public
MethodDefinition.
ImplementationDefinition<S>
invokable(
ElementMatcher<? super
MethodDescription>
matcher) {
return
invokable(new
LatentMatcher.
Resolved<
MethodDescription>(
matcher));
}
@
Override
public
Builder<S>
withHashCodeEquals() {
return
method(
isHashCode())
.
intercept(
HashCodeMethod.
usingDefaultOffset().
withIgnoredFields(
isSynthetic()))
.
method(
isEquals())
.
intercept(
EqualsMethod.
isolated().
withIgnoredFields(
isSynthetic()));
}
@
Override
public
Builder<S>
withToString() {
return
method(
isToString()).
intercept(
ToStringMethod.
prefixedBySimpleClassName());
}
@
Override
public
Builder<S>
require(
TypeDescription type, byte[]
binaryRepresentation) {
return
require(
type,
binaryRepresentation,
LoadedTypeInitializer.
NoOp.
INSTANCE);
}
@
Override
public
Builder<S>
require(
TypeDescription type, byte[]
binaryRepresentation,
LoadedTypeInitializer typeInitializer) {
return
require(new
Default(
type,
binaryRepresentation,
typeInitializer,
Collections.<
DynamicType>
emptyList()));
}
@
Override
public
Builder<S>
require(
DynamicType...
auxiliaryType) {
return
require(
Arrays.
asList(
auxiliaryType));
}
@
Override
public
Unloaded<S>
make(
TypePool typePool) {
return
make(
TypeResolutionStrategy.
Passive.
INSTANCE,
typePool);
}
@
Override
public
Unloaded<S>
make() {
return
make(
TypeResolutionStrategy.
Passive.
INSTANCE);
}
/**
* A delegator for a dynamic type builder delegating all invocations to another dynamic type builder.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
public abstract static class
Delegator<U> extends
AbstractBase<U> {
@
Override
public
Builder<U>
visit(
AsmVisitorWrapper asmVisitorWrapper) {
return
materialize().
visit(
asmVisitorWrapper);
}
@
Override
public
Builder<U>
initializer(
LoadedTypeInitializer loadedTypeInitializer) {
return
materialize().
initializer(
loadedTypeInitializer);
}
@
Override
public
Builder<U>
annotateType(
Collection<? extends
AnnotationDescription>
annotations) {
return
materialize().
annotateType(
annotations);
}
@
Override
public
Builder<U>
attribute(
TypeAttributeAppender typeAttributeAppender) {
return
materialize().
attribute(
typeAttributeAppender);
}
@
Override
public
Builder<U>
modifiers(int
modifiers) {
return
materialize().
modifiers(
modifiers);
}
@
Override
public
Builder<U>
merge(
Collection<? extends
ModifierContributor.
ForType>
modifierContributors) {
return
materialize().
merge(
modifierContributors);
}
@
Override
public
Builder<U>
name(
String name) {
return
materialize().
name(
name);
}
@
Override
public
Builder<U>
topLevelType() {
return
materialize().
topLevelType();
}
@
Override
public
InnerTypeDefinition.
ForType<U>
innerTypeOf(
TypeDescription type) {
return
materialize().
innerTypeOf(
type);
}
@
Override
public
InnerTypeDefinition<U>
innerTypeOf(
MethodDescription.
InDefinedShape methodDescription) {
return
materialize().
innerTypeOf(
methodDescription);
}
@
Override
public
Builder<U>
declaredTypes(
Collection<? extends
TypeDescription>
types) {
return
materialize().
declaredTypes(
types);
}
@
Override
public
Builder<U>
nestHost(
TypeDescription type) {
return
materialize().
nestHost(
type);
}
@
Override
public
Builder<U>
nestMembers(
Collection<? extends
TypeDescription>
types) {
return
materialize().
nestMembers(
types);
}
@
Override
public
MethodDefinition.
ImplementationDefinition.
Optional<U>
implement(
Collection<? extends
TypeDefinition>
interfaceTypes) {
return
materialize().
implement(
interfaceTypes);
}
@
Override
public
Builder<U>
initializer(
ByteCodeAppender byteCodeAppender) {
return
materialize().
initializer(
byteCodeAppender);
}
@
Override
public
Builder<U>
ignoreAlso(
ElementMatcher<? super
MethodDescription>
ignoredMethods) {
return
materialize().
ignoreAlso(
ignoredMethods);
}
@
Override
public
Builder<U>
ignoreAlso(
LatentMatcher<? super
MethodDescription>
ignoredMethods) {
return
materialize().
ignoreAlso(
ignoredMethods);
}
@
Override
public
TypeVariableDefinition<U>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds) {
return
materialize().
typeVariable(
symbol,
bounds);
}
@
Override
public
Builder<U>
transform(
ElementMatcher<? super
TypeDescription.
Generic>
matcher,
Transformer<
TypeVariableToken>
transformer) {
return
materialize().
transform(
matcher,
transformer);
}
@
Override
public
FieldDefinition.
Optional.
Valuable<U>
defineField(
String name,
TypeDefinition type, int
modifiers) {
return
materialize().
defineField(
name,
type,
modifiers);
}
@
Override
public
FieldDefinition.
Valuable<U>
field(
LatentMatcher<? super
FieldDescription>
matcher) {
return
materialize().
field(
matcher);
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<U>
defineMethod(
String name,
TypeDefinition returnType, int
modifiers) {
return
materialize().
defineMethod(
name,
returnType,
modifiers);
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<U>
defineConstructor(int
modifiers) {
return
materialize().
defineConstructor(
modifiers);
}
@
Override
public
MethodDefinition.
ImplementationDefinition<U>
invokable(
LatentMatcher<? super
MethodDescription>
matcher) {
return
materialize().
invokable(
matcher);
}
@
Override
public
Builder<U>
require(
Collection<
DynamicType>
auxiliaryTypes) {
return
materialize().
require(
auxiliaryTypes);
}
@
Override
public
DynamicType.
Unloaded<U>
make() {
return
materialize().
make();
}
@
Override
public
Unloaded<U>
make(
TypeResolutionStrategy typeResolutionStrategy) {
return
materialize().
make(
typeResolutionStrategy);
}
@
Override
public
Unloaded<U>
make(
TypePool typePool) {
return
materialize().
make(
typePool);
}
@
Override
public
Unloaded<U>
make(
TypeResolutionStrategy typeResolutionStrategy,
TypePool typePool) {
return
materialize().
make(
typeResolutionStrategy,
typePool);
}
/**
* Creates a new builder that realizes the current state of the builder.
*
* @return A new builder that realizes the current state of the builder.
*/
protected abstract
Builder<U>
materialize();
}
/**
* An adapter implementation of a dynamic type builder.
*
* @param <U> A loaded type that the built type is guaranteed to be a subclass of.
*/
@
HashCodeAndEqualsPlugin.
Enhance
public abstract static class
Adapter<U> extends
AbstractBase<U> {
/**
* The instrumented type to be created.
*/
protected final
InstrumentedType.
WithFlexibleName instrumentedType;
/**
* The current field registry.
*/
protected final
FieldRegistry fieldRegistry;
/**
* The current method registry.
*/
protected final
MethodRegistry methodRegistry;
/**
* The type attribute appender to apply onto the instrumented type.
*/
protected final
TypeAttributeAppender typeAttributeAppender;
/**
* The ASM visitor wrapper to apply onto the class writer.
*/
protected final
AsmVisitorWrapper asmVisitorWrapper;
/**
* The class file version to define auxiliary types in.
*/
protected final
ClassFileVersion classFileVersion;
/**
* The naming strategy for auxiliary types to apply.
*/
protected final
AuxiliaryType.
NamingStrategy auxiliaryTypeNamingStrategy;
/**
* The annotation value filter factory to apply.
*/
protected final
AnnotationValueFilter.
Factory annotationValueFilterFactory;
/**
* The annotation retention to apply.
*/
protected final
AnnotationRetention annotationRetention;
/**
* The implementation context factory to apply.
*/
protected final
Implementation.
Context.
Factory implementationContextFactory;
/**
* The method graph compiler to use.
*/
protected final
MethodGraph.
Compiler methodGraphCompiler;
/**
* Determines if a type should be explicitly validated.
*/
protected final
TypeValidation typeValidation;
/**
* The class writer strategy to use.
*/
protected final
ClassWriterStrategy classWriterStrategy;
/**
* A matcher for identifying methods that should be excluded from instrumentation.
*/
protected final
LatentMatcher<? super
MethodDescription>
ignoredMethods;
/**
* A list of explicitly defined auxiliary types.
*/
protected final
List<? extends
DynamicType>
auxiliaryTypes;
/**
* Creates a new default type writer for creating a new type that is not based on an existing class file.
*
* @param instrumentedType The instrumented type to be created.
* @param fieldRegistry The current field registry.
* @param methodRegistry The current method registry.
* @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
* @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
* @param classFileVersion The class file version to define auxiliary types in.
* @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
* @param annotationValueFilterFactory The annotation value filter factory to apply.
* @param annotationRetention The annotation retention to apply.
* @param implementationContextFactory The implementation context factory to apply.
* @param methodGraphCompiler The method graph compiler to use.
* @param typeValidation Determines if a type should be explicitly validated.
* @param classWriterStrategy The class writer strategy to use.
* @param ignoredMethods A matcher for identifying methods that should be excluded from instrumentation.
* @param auxiliaryTypes A list of explicitly defined auxiliary types.
*/
protected
Adapter(
InstrumentedType.
WithFlexibleName instrumentedType,
FieldRegistry fieldRegistry,
MethodRegistry methodRegistry,
TypeAttributeAppender typeAttributeAppender,
AsmVisitorWrapper asmVisitorWrapper,
ClassFileVersion classFileVersion,
AuxiliaryType.
NamingStrategy auxiliaryTypeNamingStrategy,
AnnotationValueFilter.
Factory annotationValueFilterFactory,
AnnotationRetention annotationRetention,
Implementation.
Context.
Factory implementationContextFactory,
MethodGraph.
Compiler methodGraphCompiler,
TypeValidation typeValidation,
ClassWriterStrategy classWriterStrategy,
LatentMatcher<? super
MethodDescription>
ignoredMethods,
List<? extends
DynamicType>
auxiliaryTypes) {
this.
instrumentedType =
instrumentedType;
this.
fieldRegistry =
fieldRegistry;
this.
methodRegistry =
methodRegistry;
this.
typeAttributeAppender =
typeAttributeAppender;
this.
asmVisitorWrapper =
asmVisitorWrapper;
this.
classFileVersion =
classFileVersion;
this.
auxiliaryTypeNamingStrategy =
auxiliaryTypeNamingStrategy;
this.
annotationValueFilterFactory =
annotationValueFilterFactory;
this.
annotationRetention =
annotationRetention;
this.
implementationContextFactory =
implementationContextFactory;
this.
methodGraphCompiler =
methodGraphCompiler;
this.
typeValidation =
typeValidation;
this.
classWriterStrategy =
classWriterStrategy;
this.
ignoredMethods =
ignoredMethods;
this.
auxiliaryTypes =
auxiliaryTypes;
}
@
Override
public
FieldDefinition.
Optional.
Valuable<U>
defineField(
String name,
TypeDefinition type, int
modifiers) {
return new
FieldDefinitionAdapter(new
FieldDescription.
Token(
name,
modifiers,
type.
asGenericType()));
}
@
Override
public
FieldDefinition.
Valuable<U>
field(
LatentMatcher<? super
FieldDescription>
matcher) {
return new
FieldMatchAdapter(
matcher);
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<U>
defineMethod(
String name,
TypeDefinition returnType, int
modifiers) {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
name,
modifiers,
returnType.
asGenericType()));
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Initial<U>
defineConstructor(int
modifiers) {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
modifiers));
}
@
Override
public
MethodDefinition.
ImplementationDefinition<U>
invokable(
LatentMatcher<? super
MethodDescription>
matcher) {
return new
MethodMatchAdapter(
matcher);
}
@
Override
public
MethodDefinition.
ImplementationDefinition.
Optional<U>
implement(
Collection<? extends
TypeDefinition>
interfaceTypes) {
return new
OptionalMethodMatchAdapter(new
TypeList.
Generic.
Explicit(new
ArrayList<
TypeDefinition>(
interfaceTypes)));
}
@
Override
@
SuppressWarnings("unchecked") // In absence of @SafeVarargs for Java 6
public
Builder<U>
ignoreAlso(
LatentMatcher<? super
MethodDescription>
ignoredMethods) {
return
materialize(
instrumentedType,
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
new
LatentMatcher.
Disjunction<
MethodDescription>(this.
ignoredMethods,
ignoredMethods),
auxiliaryTypes);
}
@
Override
public
Builder<U>
initializer(
ByteCodeAppender byteCodeAppender) {
return
materialize(
instrumentedType.
withInitializer(
byteCodeAppender),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
initializer(
LoadedTypeInitializer loadedTypeInitializer) {
return
materialize(
instrumentedType.
withInitializer(
loadedTypeInitializer),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
name(
String name) {
return
materialize(
instrumentedType.
withName(
name),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
modifiers(int
modifiers) {
return
materialize(
instrumentedType.
withModifiers(
modifiers),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
merge(
Collection<? extends
ModifierContributor.
ForType>
modifierContributors) {
return
materialize(
instrumentedType.
withModifiers(
ModifierContributor.
Resolver.
of(
modifierContributors).
resolve(
instrumentedType.
getModifiers())),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
topLevelType() {
return
Adapter.this.
materialize(
instrumentedType
.
withDeclaringType(
TypeDescription.
UNDEFINED)
.
withEnclosingType(
TypeDescription.
UNDEFINED)
.
withLocalClass(false),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
InnerTypeDefinition.
ForType<U>
innerTypeOf(
TypeDescription type) {
return new
InnerTypeDefinitionForTypeAdapter(
type);
}
@
Override
public
InnerTypeDefinition<U>
innerTypeOf(
MethodDescription.
InDefinedShape methodDescription) {
return
methodDescription.
isTypeInitializer()
? new
InnerTypeDefinitionForTypeAdapter(
methodDescription.
getDeclaringType())
: new
InnerTypeDefinitionForMethodAdapter(
methodDescription);
}
@
Override
public
Builder<U>
declaredTypes(
Collection<? extends
TypeDescription>
types) {
return
materialize(
instrumentedType.
withDeclaredTypes(new
TypeList.
Explicit(new
ArrayList<
TypeDescription>(
types))),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
nestHost(
TypeDescription type) {
return
materialize(
instrumentedType.
withNestHost(
type),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
nestMembers(
Collection<? extends
TypeDescription>
types) {
return
materialize(
instrumentedType.
withNestMembers(new
TypeList.
Explicit(new
ArrayList<
TypeDescription>(
types))),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
TypeVariableDefinition<U>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds) {
return new
TypeVariableDefinitionAdapter(new
TypeVariableToken(
symbol, new
TypeList.
Generic.
Explicit(new
ArrayList<
TypeDefinition>(
bounds))));
}
@
Override
public
Builder<U>
transform(
ElementMatcher<? super
TypeDescription.
Generic>
matcher,
Transformer<
TypeVariableToken>
transformer) {
return
materialize(
instrumentedType.
withTypeVariables(
matcher,
transformer),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
attribute(
TypeAttributeAppender typeAttributeAppender) {
return
materialize(
instrumentedType,
fieldRegistry,
methodRegistry,
new
TypeAttributeAppender.
Compound(this.
typeAttributeAppender,
typeAttributeAppender),
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
annotateType(
Collection<? extends
AnnotationDescription>
annotations) {
return
materialize(
instrumentedType.
withAnnotations(new
ArrayList<
AnnotationDescription>(
annotations)),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
visit(
AsmVisitorWrapper asmVisitorWrapper) {
return
materialize(
instrumentedType,
fieldRegistry,
methodRegistry,
typeAttributeAppender,
new
AsmVisitorWrapper.
Compound(this.
asmVisitorWrapper,
asmVisitorWrapper),
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
require(
Collection<
DynamicType>
auxiliaryTypes) {
return
materialize(
instrumentedType,
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
CompoundList.
of(this.
auxiliaryTypes, new
ArrayList<
DynamicType>(
auxiliaryTypes)));
}
/**
* Materializes the supplied state of a dynamic type builder.
*
* @param instrumentedType The instrumented type.
* @param fieldRegistry The current field registry.
* @param methodRegistry The current method registry.
* @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
* @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
* @param classFileVersion The class file version to define auxiliary types in.
* @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
* @param annotationValueFilterFactory The annotation value filter factory to apply.
* @param annotationRetention The annotation retention to apply.
* @param implementationContextFactory The implementation context factory to apply.
* @param methodGraphCompiler The method graph compiler to use.
* @param typeValidation The type validation state.
* @param classWriterStrategy The class writer strategy to use.
* @param ignoredMethods A matcher for identifying methods that should be excluded from instrumentation.
* @param auxiliaryTypes A list of explicitly required auxiliary types.
* @return A type builder that represents the supplied arguments.
*/
protected abstract
Builder<U>
materialize(
InstrumentedType.
WithFlexibleName instrumentedType,
FieldRegistry fieldRegistry,
MethodRegistry methodRegistry,
TypeAttributeAppender typeAttributeAppender,
AsmVisitorWrapper asmVisitorWrapper,
ClassFileVersion classFileVersion,
AuxiliaryType.
NamingStrategy auxiliaryTypeNamingStrategy,
AnnotationValueFilter.
Factory annotationValueFilterFactory,
AnnotationRetention annotationRetention,
Implementation.
Context.
Factory implementationContextFactory,
MethodGraph.
Compiler methodGraphCompiler,
TypeValidation typeValidation,
ClassWriterStrategy classWriterStrategy,
LatentMatcher<? super
MethodDescription>
ignoredMethods,
List<? extends
DynamicType>
auxiliaryTypes);
/**
* An adapter for applying an inner type definition for an outer type.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
InnerTypeDefinitionForTypeAdapter extends
Builder.
AbstractBase.
Delegator<U> implements
InnerTypeDefinition.
ForType<U> {
/**
* A description of the type that is the defined outer type.
*/
private final
TypeDescription typeDescription;
/**
* Creates a new adapter for an inner type definition for an outer type.
*
* @param typeDescription A description of the type that is the defined outer type.
*/
protected
InnerTypeDefinitionForTypeAdapter(
TypeDescription typeDescription) {
this.
typeDescription =
typeDescription;
}
@
Override
public
Builder<U>
asAnonymousType() {
return
Adapter.this.
materialize(
instrumentedType
.
withDeclaringType(
TypeDescription.
UNDEFINED)
.
withEnclosingType(
typeDescription)
.
withAnonymousClass(true),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
Builder<U>
asMemberType() {
return
Adapter.this.
materialize(
instrumentedType
.
withDeclaringType(
typeDescription)
.
withEnclosingType(
typeDescription)
.
withAnonymousClass(false)
.
withLocalClass(false),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
protected
Builder<U>
materialize() {
return
Adapter.this.
materialize(
instrumentedType
.
withDeclaringType(
TypeDescription.
UNDEFINED)
.
withEnclosingType(
typeDescription)
.
withLocalClass(true),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
}
/**
* An adapter for applying an inner type definition for an outer method or constructor.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
InnerTypeDefinitionForMethodAdapter extends
Builder.
AbstractBase.
Delegator<U> implements
InnerTypeDefinition<U> {
/**
* A description of the declaring method or constructor.
*/
private final
MethodDescription.
InDefinedShape methodDescription;
/**
* Creates a new adapter for defining a type that is declared within a method or constructor.
*
* @param methodDescription A description of the declaring method or constructor.
*/
protected
InnerTypeDefinitionForMethodAdapter(
MethodDescription.
InDefinedShape methodDescription) {
this.
methodDescription =
methodDescription;
}
@
Override
public
Builder<U>
asAnonymousType() {
return
Adapter.this.
materialize(
instrumentedType
.
withDeclaringType(
TypeDescription.
UNDEFINED)
.
withEnclosingMethod(
methodDescription)
.
withAnonymousClass(true),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
protected
Builder<U>
materialize() {
return
Adapter.this.
materialize(
instrumentedType
.
withDeclaringType(
TypeDescription.
UNDEFINED)
.
withEnclosingMethod(
methodDescription)
.
withLocalClass(true),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
}
/**
* An adapter for defining a new type variable for the instrumented type.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
TypeVariableDefinitionAdapter extends
TypeVariableDefinition.
AbstractBase<U> {
/**
* The current definition of the type variable.
*/
private final
TypeVariableToken token;
/**
* Creates a new type variable definition adapter.
*
* @param token The current definition of the type variable.
*/
protected
TypeVariableDefinitionAdapter(
TypeVariableToken token) {
this.
token =
token;
}
@
Override
public
TypeVariableDefinition<U>
annotateTypeVariable(
Collection<? extends
AnnotationDescription>
annotations) {
return new
TypeVariableDefinitionAdapter(new
TypeVariableToken(
token.
getSymbol(),
token.
getBounds(),
CompoundList.
of(
token.
getAnnotations(), new
ArrayList<
AnnotationDescription>(
annotations))));
}
@
Override
protected
Builder<U>
materialize() {
return
Adapter.this.
materialize(
instrumentedType.
withTypeVariable(
token),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
}
/**
* An adapter for defining a new field.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
FieldDefinitionAdapter extends
FieldDefinition.
Optional.
Valuable.
AbstractBase.
Adapter<U> {
/**
* The token representing the current field definition.
*/
private final
FieldDescription.
Token token;
/**
* Creates a new field definition adapter.
*
* @param token The token representing the current field definition.
*/
protected
FieldDefinitionAdapter(
FieldDescription.
Token token) {
this(
FieldAttributeAppender.
ForInstrumentedField.
INSTANCE,
Transformer.
NoOp.<
FieldDescription>
make(),
FieldDescription.
NO_DEFAULT_VALUE,
token);
}
/**
* Creates a new field definition adapter.
*
* @param fieldAttributeAppenderFactory The field attribute appender factory to apply.
* @param transformer The field transformer to apply.
* @param defaultValue The field's default value or {@code null} if no value is to be defined.
* @param token The token representing the current field definition.
*/
protected
FieldDefinitionAdapter(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory,
Transformer<
FieldDescription>
transformer,
Object defaultValue,
FieldDescription.
Token token) {
super(
fieldAttributeAppenderFactory,
transformer,
defaultValue);
this.
token =
token;
}
@
Override
public
Optional<U>
annotateField(
Collection<? extends
AnnotationDescription>
annotations) {
return new
FieldDefinitionAdapter(
fieldAttributeAppenderFactory,
transformer,
defaultValue, new
FieldDescription.
Token(
token.
getName(),
token.
getModifiers(),
token.
getType(),
CompoundList.
of(
token.
getAnnotations(), new
ArrayList<
AnnotationDescription>(
annotations))));
}
@
Override
protected
Builder<U>
materialize() {
return
Builder.
AbstractBase.
Adapter.this.
materialize(
instrumentedType.
withField(
token),
fieldRegistry.
prepend(new
LatentMatcher.
ForFieldToken(
token),
fieldAttributeAppenderFactory,
defaultValue,
transformer),
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
protected
Optional<U>
materialize(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory,
Transformer<
FieldDescription>
transformer,
Object defaultValue) {
return new
FieldDefinitionAdapter(
fieldAttributeAppenderFactory,
transformer,
defaultValue,
token);
}
}
/**
* An adapter for matching an existing field.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
FieldMatchAdapter extends
FieldDefinition.
Optional.
Valuable.
AbstractBase.
Adapter<U> {
/**
* The matcher for any fields to apply this matcher to.
*/
private final
LatentMatcher<? super
FieldDescription>
matcher;
/**
* Creates a new field match adapter.
*
* @param matcher The matcher for any fields to apply this matcher to.
*/
protected
FieldMatchAdapter(
LatentMatcher<? super
FieldDescription>
matcher) {
this(
FieldAttributeAppender.
NoOp.
INSTANCE,
Transformer.
NoOp.<
FieldDescription>
make(),
FieldDescription.
NO_DEFAULT_VALUE,
matcher);
}
/**
* Creates a new field match adapter.
*
* @param fieldAttributeAppenderFactory The field attribute appender factory to apply.
* @param transformer The field transformer to apply.
* @param defaultValue The field's default value or {@code null} if no value is to be defined.
* @param matcher The matcher for any fields to apply this matcher to.
*/
protected
FieldMatchAdapter(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory,
Transformer<
FieldDescription>
transformer,
Object defaultValue,
LatentMatcher<? super
FieldDescription>
matcher) {
super(
fieldAttributeAppenderFactory,
transformer,
defaultValue);
this.
matcher =
matcher;
}
@
Override
public
Optional<U>
annotateField(
Collection<? extends
AnnotationDescription>
annotations) {
return
attribute(new
FieldAttributeAppender.
Explicit(new
ArrayList<
AnnotationDescription>(
annotations)));
}
@
Override
protected
Builder<U>
materialize() {
return
Builder.
AbstractBase.
Adapter.this.
materialize(
instrumentedType,
fieldRegistry.
prepend(
matcher,
fieldAttributeAppenderFactory,
defaultValue,
transformer),
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
protected
Optional<U>
materialize(
FieldAttributeAppender.
Factory fieldAttributeAppenderFactory,
Transformer<
FieldDescription>
transformer,
Object defaultValue) {
return new
FieldMatchAdapter(
fieldAttributeAppenderFactory,
transformer,
defaultValue,
matcher);
}
}
/**
* An adapter for defining a new method.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
MethodDefinitionAdapter extends
MethodDefinition.
ParameterDefinition.
Initial.
AbstractBase<U> {
/**
* A token representing the currently defined method.
*/
private final
MethodDescription.
Token token;
/**
* Creates a new method definition adapter.
*
* @param token A token representing the currently defined method.
*/
protected
MethodDefinitionAdapter(
MethodDescription.
Token token) {
this.
token =
token;
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Annotatable<U>
withParameter(
TypeDefinition type,
String name, int
modifiers) {
return new
ParameterAnnotationAdapter(new
ParameterDescription.
Token(
type.
asGenericType(),
name,
modifiers));
}
@
Override
public
Simple.
Annotatable<U>
withParameter(
TypeDefinition type) {
return new
SimpleParameterAnnotationAdapter(new
ParameterDescription.
Token(
type.
asGenericType()));
}
@
Override
public
MethodDefinition.
ExceptionDefinition<U>
throwing(
Collection<? extends
TypeDefinition>
types) {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
token.
getName(),
token.
getModifiers(),
token.
getTypeVariableTokens(),
token.
getReturnType(),
token.
getParameterTokens(),
CompoundList.
of(
token.
getExceptionTypes(), new
TypeList.
Generic.
Explicit(new
ArrayList<
TypeDefinition>(
types))),
token.
getAnnotations(),
token.
getDefaultValue(),
token.
getReceiverType()));
}
@
Override
public
MethodDefinition.
TypeVariableDefinition.
Annotatable<U>
typeVariable(
String symbol,
Collection<? extends
TypeDefinition>
bounds) {
return new
TypeVariableAnnotationAdapter(new
TypeVariableToken(
symbol, new
TypeList.
Generic.
Explicit(new
ArrayList<
TypeDefinition>(
bounds))));
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
intercept(
Implementation implementation) {
return
materialize(new
MethodRegistry.
Handler.
ForImplementation(
implementation));
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
withoutCode() {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
token.
getName(),
ModifierContributor.
Resolver.
of(
MethodManifestation.
ABSTRACT).
resolve(
token.
getModifiers()),
token.
getTypeVariableTokens(),
token.
getReturnType(),
token.
getParameterTokens(),
token.
getExceptionTypes(),
token.
getAnnotations(),
token.
getDefaultValue(),
token.
getReceiverType())).
materialize(
MethodRegistry.
Handler.
ForAbstractMethod.
INSTANCE);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
defaultValue(
AnnotationValue<?, ?>
annotationValue) {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
token.
getName(),
ModifierContributor.
Resolver.
of(
MethodManifestation.
ABSTRACT).
resolve(
token.
getModifiers()),
token.
getTypeVariableTokens(),
token.
getReturnType(),
token.
getParameterTokens(),
token.
getExceptionTypes(),
token.
getAnnotations(),
annotationValue,
token.
getReceiverType())).
materialize(new
MethodRegistry.
Handler.
ForAnnotationValue(
annotationValue));
}
/**
* Materializes the given handler as the implementation.
*
* @param handler The handler for implementing the method.
* @return A method definition for the given handler.
*/
private
MethodDefinition.
ReceiverTypeDefinition<U>
materialize(
MethodRegistry.
Handler handler) {
return new
AnnotationAdapter(
handler);
}
/**
* An adapter for defining a new type variable for the currently defined method.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
TypeVariableAnnotationAdapter extends
MethodDefinition.
TypeVariableDefinition.
Annotatable.
AbstractBase.
Adapter<U> {
/**
* The currently defined type variable.
*/
private final
TypeVariableToken token;
/**
* Creates a new type variable annotation adapter.
*
* @param token The currently defined type variable.
*/
protected
TypeVariableAnnotationAdapter(
TypeVariableToken token) {
this.
token =
token;
}
@
Override
protected
MethodDefinition.
ParameterDefinition<U>
materialize() {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
MethodDefinitionAdapter.this.
token.
getName(),
MethodDefinitionAdapter.this.
token.
getModifiers(),
CompoundList.
of(
MethodDefinitionAdapter.this.
token.
getTypeVariableTokens(),
token),
MethodDefinitionAdapter.this.
token.
getReturnType(),
MethodDefinitionAdapter.this.
token.
getParameterTokens(),
MethodDefinitionAdapter.this.
token.
getExceptionTypes(),
MethodDefinitionAdapter.this.
token.
getAnnotations(),
MethodDefinitionAdapter.this.
token.
getDefaultValue(),
MethodDefinitionAdapter.this.
token.
getReceiverType()));
}
@
Override
public
Annotatable<U>
annotateTypeVariable(
Collection<? extends
AnnotationDescription>
annotations) {
return new
TypeVariableAnnotationAdapter(new
TypeVariableToken(
token.
getSymbol(),
token.
getBounds(),
CompoundList.
of(
token.
getAnnotations(), new
ArrayList<
AnnotationDescription>(
annotations))));
}
}
/**
* An annotation adapter for a parameter definition.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
ParameterAnnotationAdapter extends
MethodDefinition.
ParameterDefinition.
Annotatable.
AbstractBase.
Adapter<U> {
/**
* The token of the currently defined parameter.
*/
private final
ParameterDescription.
Token token;
/**
* Creates a new parameter annotation adapter.
*
* @param token The token of the currently defined parameter.
*/
protected
ParameterAnnotationAdapter(
ParameterDescription.
Token token) {
this.
token =
token;
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Annotatable<U>
annotateParameter(
Collection<? extends
AnnotationDescription>
annotations) {
return new
ParameterAnnotationAdapter(new
ParameterDescription.
Token(
token.
getType(),
CompoundList.
of(
token.
getAnnotations(), new
ArrayList<
AnnotationDescription>(
annotations)),
token.
getName(),
token.
getModifiers()));
}
@
Override
protected
MethodDefinition.
ParameterDefinition<U>
materialize() {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
MethodDefinitionAdapter.this.
token.
getName(),
MethodDefinitionAdapter.this.
token.
getModifiers(),
MethodDefinitionAdapter.this.
token.
getTypeVariableTokens(),
MethodDefinitionAdapter.this.
token.
getReturnType(),
CompoundList.
of(
MethodDefinitionAdapter.this.
token.
getParameterTokens(),
token),
MethodDefinitionAdapter.this.
token.
getExceptionTypes(),
MethodDefinitionAdapter.this.
token.
getAnnotations(),
MethodDefinitionAdapter.this.
token.
getDefaultValue(),
MethodDefinitionAdapter.this.
token.
getReceiverType()));
}
}
/**
* An annotation adapter for a simple parameter definition.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
SimpleParameterAnnotationAdapter extends
MethodDefinition.
ParameterDefinition.
Simple.
Annotatable.
AbstractBase.
Adapter<U> {
/**
* The token of the currently defined parameter.
*/
private final
ParameterDescription.
Token token;
/**
* Creates a new simple parameter annotation adapter.
*
* @param token The token of the currently defined parameter.
*/
protected
SimpleParameterAnnotationAdapter(
ParameterDescription.
Token token) {
this.
token =
token;
}
@
Override
public
MethodDefinition.
ParameterDefinition.
Simple.
Annotatable<U>
annotateParameter(
Collection<? extends
AnnotationDescription>
annotations) {
return new
SimpleParameterAnnotationAdapter(new
ParameterDescription.
Token(
token.
getType(),
CompoundList.
of(
token.
getAnnotations(), new
ArrayList<
AnnotationDescription>(
annotations)),
token.
getName(),
token.
getModifiers()));
}
@
Override
protected
MethodDefinition.
ParameterDefinition.
Simple<U>
materialize() {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
MethodDefinitionAdapter.this.
token.
getName(),
MethodDefinitionAdapter.this.
token.
getModifiers(),
MethodDefinitionAdapter.this.
token.
getTypeVariableTokens(),
MethodDefinitionAdapter.this.
token.
getReturnType(),
CompoundList.
of(
MethodDefinitionAdapter.this.
token.
getParameterTokens(),
token),
MethodDefinitionAdapter.this.
token.
getExceptionTypes(),
MethodDefinitionAdapter.this.
token.
getAnnotations(),
MethodDefinitionAdapter.this.
token.
getDefaultValue(),
MethodDefinitionAdapter.this.
token.
getReceiverType()));
}
}
/**
* An annotation adapter for a method definition.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
AnnotationAdapter extends
MethodDefinition.
AbstractBase.
Adapter<U> {
/**
* Creates a new annotation adapter.
*
* @param handler The handler that determines how a method is implemented.
*/
protected
AnnotationAdapter(
MethodRegistry.
Handler handler) {
this(
handler,
MethodAttributeAppender.
ForInstrumentedMethod.
INCLUDING_RECEIVER,
Transformer.
NoOp.<
MethodDescription>
make());
}
/**
* Creates a new annotation adapter.
*
* @param handler The handler that determines how a method is implemented.
* @param methodAttributeAppenderFactory The method attribute appender factory to apply onto the method that is currently being implemented.
* @param transformer The method transformer to apply onto the method that is currently being implemented.
*/
protected
AnnotationAdapter(
MethodRegistry.
Handler handler,
MethodAttributeAppender.
Factory methodAttributeAppenderFactory,
Transformer<
MethodDescription>
transformer) {
super(
handler,
methodAttributeAppenderFactory,
transformer);
}
@
Override
public
MethodDefinition<U>
receiverType(
TypeDescription.
Generic receiverType) {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
token.
getName(),
token.
getModifiers(),
token.
getTypeVariableTokens(),
token.
getReturnType(),
token.
getParameterTokens(),
token.
getExceptionTypes(),
token.
getAnnotations(),
token.
getDefaultValue(),
receiverType)).new
AnnotationAdapter(
handler,
methodAttributeAppenderFactory,
transformer);
}
@
Override
public
MethodDefinition<U>
annotateMethod(
Collection<? extends
AnnotationDescription>
annotations) {
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
token.
getName(),
token.
getModifiers(),
token.
getTypeVariableTokens(),
token.
getReturnType(),
token.
getParameterTokens(),
token.
getExceptionTypes(),
CompoundList.
of(
token.
getAnnotations(), new
ArrayList<
AnnotationDescription>(
annotations)),
token.
getDefaultValue(),
token.
getReceiverType())).new
AnnotationAdapter(
handler,
methodAttributeAppenderFactory,
transformer);
}
@
Override
public
MethodDefinition<U>
annotateParameter(int
index,
Collection<? extends
AnnotationDescription>
annotations) {
List<
ParameterDescription.
Token>
parameterTokens = new
ArrayList<
ParameterDescription.
Token>(
token.
getParameterTokens());
parameterTokens.
set(
index, new
ParameterDescription.
Token(
token.
getParameterTokens().
get(
index).
getType(),
CompoundList.
of(
token.
getParameterTokens().
get(
index).
getAnnotations(), new
ArrayList<
AnnotationDescription>(
annotations)),
token.
getParameterTokens().
get(
index).
getName(),
token.
getParameterTokens().
get(
index).
getModifiers()));
return new
MethodDefinitionAdapter(new
MethodDescription.
Token(
token.
getName(),
token.
getModifiers(),
token.
getTypeVariableTokens(),
token.
getReturnType(),
parameterTokens,
token.
getExceptionTypes(),
token.
getAnnotations(),
token.
getDefaultValue(),
token.
getReceiverType())).new
AnnotationAdapter(
handler,
methodAttributeAppenderFactory,
transformer);
}
@
Override
protected
MethodDefinition<U>
materialize(
MethodRegistry.
Handler handler,
MethodAttributeAppender.
Factory methodAttributeAppenderFactory,
Transformer<
MethodDescription>
transformer) {
return new
AnnotationAdapter(
handler,
methodAttributeAppenderFactory,
transformer);
}
@
Override
protected
Builder<U>
materialize() {
return
Builder.
AbstractBase.
Adapter.this.
materialize(
instrumentedType.
withMethod(
token),
fieldRegistry,
methodRegistry.
prepend(new
LatentMatcher.
ForMethodToken(
token),
handler,
methodAttributeAppenderFactory,
transformer),
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
}
}
/**
* An adapter for matching an existing method.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
MethodMatchAdapter extends
MethodDefinition.
ImplementationDefinition.
AbstractBase<U> {
/**
* The method matcher of this adapter.
*/
private final
LatentMatcher<? super
MethodDescription>
matcher;
/**
* Creates a new method match adapter.
*
* @param matcher The method matcher of this adapter.
*/
protected
MethodMatchAdapter(
LatentMatcher<? super
MethodDescription>
matcher) {
this.
matcher =
matcher;
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
intercept(
Implementation implementation) {
return
materialize(new
MethodRegistry.
Handler.
ForImplementation(
implementation));
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
withoutCode() {
return
materialize(
MethodRegistry.
Handler.
ForAbstractMethod.
INSTANCE);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
defaultValue(
AnnotationValue<?, ?>
annotationValue) {
return
materialize(new
MethodRegistry.
Handler.
ForAnnotationValue(
annotationValue));
}
/**
* Materializes the method definition with the supplied handler.
*
* @param handler The handler that implements any method matched by this instances matcher.
* @return A method definition where any matched method is implemented by the supplied handler.
*/
private
MethodDefinition.
ReceiverTypeDefinition<U>
materialize(
MethodRegistry.
Handler handler) {
return new
AnnotationAdapter(
handler);
}
/**
* An annotation adapter for implementing annotations during a method definition.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
AnnotationAdapter extends
MethodDefinition.
AbstractBase.
Adapter<U> {
/**
* Creates a new annotation adapter.
*
* @param handler The handler that determines how a method is implemented.
*/
protected
AnnotationAdapter(
MethodRegistry.
Handler handler) {
this(
handler,
MethodAttributeAppender.
NoOp.
INSTANCE,
Transformer.
NoOp.<
MethodDescription>
make());
}
/**
* Creates a new annotation adapter.
*
* @param handler The handler that determines how a method is implemented.
* @param methodAttributeAppenderFactory The method attribute appender factory to apply onto the method that is currently being implemented.
* @param transformer The method transformer to apply onto the method that is currently being implemented.
*/
protected
AnnotationAdapter(
MethodRegistry.
Handler handler,
MethodAttributeAppender.
Factory methodAttributeAppenderFactory,
Transformer<
MethodDescription>
transformer) {
super(
handler,
methodAttributeAppenderFactory,
transformer);
}
@
Override
public
MethodDefinition<U>
receiverType(
TypeDescription.
Generic receiverType) {
return new
AnnotationAdapter(
handler,
new
MethodAttributeAppender.
Factory.
Compound(
methodAttributeAppenderFactory, new
MethodAttributeAppender.
ForReceiverType(
receiverType)),
transformer);
}
@
Override
public
MethodDefinition<U>
annotateMethod(
Collection<? extends
AnnotationDescription>
annotations) {
return new
AnnotationAdapter(
handler,
new
MethodAttributeAppender.
Factory.
Compound(
methodAttributeAppenderFactory, new
MethodAttributeAppender.
Explicit(new
ArrayList<
AnnotationDescription>(
annotations))),
transformer);
}
@
Override
public
MethodDefinition<U>
annotateParameter(int
index,
Collection<? extends
AnnotationDescription>
annotations) {
return new
AnnotationAdapter(
handler,
new
MethodAttributeAppender.
Factory.
Compound(
methodAttributeAppenderFactory, new
MethodAttributeAppender.
Explicit(
index, new
ArrayList<
AnnotationDescription>(
annotations))),
transformer);
}
@
Override
protected
MethodDefinition<U>
materialize(
MethodRegistry.
Handler handler,
MethodAttributeAppender.
Factory methodAttributeAppenderFactory,
Transformer<
MethodDescription>
transformer) {
return new
AnnotationAdapter(
handler,
methodAttributeAppenderFactory,
transformer);
}
@
Override
protected
Builder<U>
materialize() {
return
Builder.
AbstractBase.
Adapter.this.
materialize(
instrumentedType,
fieldRegistry,
methodRegistry.
prepend(
matcher,
handler,
methodAttributeAppenderFactory,
transformer),
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
}
}
/**
* An adapter for optionally matching methods defined by declared interfaces.
*/
@
HashCodeAndEqualsPlugin.
Enhance(includeSyntheticFields = true)
protected class
OptionalMethodMatchAdapter extends
Builder.
AbstractBase.
Delegator<U> implements
MethodDefinition.
ImplementationDefinition.
Optional<U> {
/**
* The interfaces whose methods are optionally matched.
*/
private final
TypeList.
Generic interfaces;
/**
* Creates a new optional method match adapter.
*
* @param interfaces The interfaces whose methods are optionally matched.
*/
protected
OptionalMethodMatchAdapter(
TypeList.
Generic interfaces) {
this.
interfaces =
interfaces;
}
@
Override
protected
Builder<U>
materialize() {
return
Adapter.this.
materialize(
instrumentedType.
withInterfaces(
interfaces),
fieldRegistry,
methodRegistry,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
intercept(
Implementation implementation) {
return
interfaceType().
intercept(
implementation);
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
withoutCode() {
return
interfaceType().
withoutCode();
}
@
Override
public
MethodDefinition.
ReceiverTypeDefinition<U>
defaultValue(
AnnotationValue<?, ?>
annotationValue) {
return
interfaceType().
defaultValue(
annotationValue);
}
@
Override
public <V>
MethodDefinition.
ReceiverTypeDefinition<U>
defaultValue(V
value,
Class<? extends V>
type) {
return
interfaceType().
defaultValue(
value,
type);
}
/**
* Returns a matcher for the interfaces' methods.
*
* @return A matcher for the interfaces' methods.
*/
private
MethodDefinition.
ImplementationDefinition<U>
interfaceType() {
ElementMatcher.
Junction<
TypeDescription>
elementMatcher =
none();
for (
TypeDescription typeDescription :
interfaces.
asErasures()) {
elementMatcher =
elementMatcher.
or(
isSuperTypeOf(
typeDescription));
}
return
materialize().
invokable(
isDeclaredBy(
isInterface().
and(
elementMatcher)));
}
}
}
}
}
/**
* A dynamic type that has not yet been loaded by a given {@link java.lang.ClassLoader}.
*
* @param <T> The most specific known loaded type that is implemented by this dynamic type, usually the
* type itself, an interface or the direct super class.
*/
interface
Unloaded<T> extends
DynamicType {
/**
* Attempts to load this dynamic type including all of its auxiliary types, if any. If the class loader
* is the bootstrap class loader, a new class loader is created for loading those types. If the class loader
* is an instance of {@link InjectionClassLoader}, the class is injected. And otherwise, the types are injected
* into the provided class loader.
*
* @param classLoader The class loader to use for this class loading.
* @return This dynamic type in its loaded state.
*/
Loaded<T>
load(
ClassLoader classLoader);
/**
* Attempts to load this dynamic type including all of its auxiliary types, if any.
*
* @param classLoader The class loader to use for this class loading.
* @param classLoadingStrategy The class loader strategy which should be used for this class loading.
* @param <S> The least specific type of class loader this strategy can apply to.
* @return This dynamic type in its loaded state.
* @see net.bytebuddy.dynamic.loading.ClassLoadingStrategy.Default
*/
<S extends
ClassLoader>
Loaded<T>
load(S
classLoader,
ClassLoadingStrategy<? super S>
classLoadingStrategy);
/**
* Includes the provided dynamic types as auxiliary types of this instance.
*
* @param dynamicType The dynamic types to include.
* @return A copy of this unloaded dynamic type which includes the provided dynamic types.
*/
Unloaded<T>
include(
DynamicType...
dynamicType);
/**
* Includes the provided dynamic types as auxiliary types of this instance.
*
* @param dynamicTypes The dynamic types to include.
* @return A copy of this unloaded dynamic type which includes the provided dynamic types.
*/
Unloaded<T>
include(
List<? extends
DynamicType>
dynamicTypes);
}
/**
* A dynamic type that has been loaded into the running instance of the Java virtual machine.
*
* @param <T> The most specific known loaded type that is implemented by this dynamic type, usually the
* type itself, an interface or the direct super class.
*/
interface
Loaded<T> extends
DynamicType {
/**
* Returns the loaded main class.
*
* @return A loaded class representation of this dynamic type.
*/
Class<? extends T>
getLoaded();
/**
* <p>
* Returns a map of all loaded auxiliary types to this dynamic type.
* </p>
* <p>
* <b>Note</b>: The type descriptions will most likely differ from the binary representation of this type.
* Normally, annotations and intercepted methods are not added to the type descriptions of auxiliary types.
* </p>
*
* @return A mapping from the fully qualified names of all auxiliary types to their loaded class representations.
*/
Map<
TypeDescription,
Class<?>>
getLoadedAuxiliaryTypes();
}
/**
* A default implementation of a dynamic type.
*/
@
HashCodeAndEqualsPlugin.
Enhance
class
Default implements
DynamicType {
/**
* The file name extension for Java class files.
*/
private static final
String CLASS_FILE_EXTENSION = ".class";
/**
* The default version of a jar file manifest.
*/
private static final
String MANIFEST_VERSION = "1.0";
/**
* The size of a writing buffer.
*/
private static final int
BUFFER_SIZE = 1024;
/**
* A convenience index for the beginning of an array to improve the readability of the code.
*/
private static final int
FROM_BEGINNING = 0;
/**
* A convenience representative of an {@link java.io.InputStream}'s end to improve the readability of the code.
*/
private static final int
END_OF_FILE = -1;
/**
* A suffix for temporary files.
*/
private static final
String TEMP_SUFFIX = "tmp";
/**
* A type description of this dynamic type.
*/
protected final
TypeDescription typeDescription;
/**
* The byte array representing this dynamic type.
*/
protected final byte[]
binaryRepresentation;
/**
* The loaded type initializer for this dynamic type.
*/
protected final
LoadedTypeInitializer loadedTypeInitializer;
/**
* A list of auxiliary types for this dynamic type.
*/
protected final
List<? extends
DynamicType>
auxiliaryTypes;
/**
* Creates a new dynamic type.
*
* @param typeDescription A description of this dynamic type.
* @param binaryRepresentation A byte array containing the binary representation of this dynamic type. The array must not be modified.
* @param loadedTypeInitializer The loaded type initializer of this dynamic type.
* @param auxiliaryTypes The auxiliary type required for this dynamic type.
*/
@
SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "The array is not to be modified by contract")
public
Default(
TypeDescription typeDescription,
byte[]
binaryRepresentation,
LoadedTypeInitializer loadedTypeInitializer,
List<? extends
DynamicType>
auxiliaryTypes) {
this.
typeDescription =
typeDescription;
this.
binaryRepresentation =
binaryRepresentation;
this.
loadedTypeInitializer =
loadedTypeInitializer;
this.
auxiliaryTypes =
auxiliaryTypes;
}
@
Override
public
TypeDescription getTypeDescription() {
return
typeDescription;
}
@
Override
public
Map<
TypeDescription, byte[]>
getAllTypes() {
Map<
TypeDescription, byte[]>
allTypes = new
LinkedHashMap<
TypeDescription, byte[]>();
allTypes.
put(
typeDescription,
binaryRepresentation);
for (
DynamicType auxiliaryType :
auxiliaryTypes) {
allTypes.
putAll(
auxiliaryType.
getAllTypes());
}
return
allTypes;
}
@
Override
public
Map<
TypeDescription,
LoadedTypeInitializer>
getLoadedTypeInitializers() {
Map<
TypeDescription,
LoadedTypeInitializer>
classLoadingCallbacks = new
HashMap<
TypeDescription,
LoadedTypeInitializer>();
for (
DynamicType auxiliaryType :
auxiliaryTypes) {
classLoadingCallbacks.
putAll(
auxiliaryType.
getLoadedTypeInitializers());
}
classLoadingCallbacks.
put(
typeDescription,
loadedTypeInitializer);
return
classLoadingCallbacks;
}
@
Override
public boolean
hasAliveLoadedTypeInitializers() {
for (
LoadedTypeInitializer loadedTypeInitializer :
getLoadedTypeInitializers().
values()) {
if (
loadedTypeInitializer.
isAlive()) {
return true;
}
}
return false;
}
@
Override
@
SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "The array is not to be modified by contract")
public byte[]
getBytes() {
return
binaryRepresentation;
}
@
Override
public
Map<
TypeDescription, byte[]>
getAuxiliaryTypes() {
Map<
TypeDescription, byte[]>
auxiliaryTypes = new
HashMap<
TypeDescription, byte[]>();
for (
DynamicType auxiliaryType : this.
auxiliaryTypes) {
auxiliaryTypes.
put(
auxiliaryType.
getTypeDescription(),
auxiliaryType.
getBytes());
auxiliaryTypes.
putAll(
auxiliaryType.
getAuxiliaryTypes());
}
return
auxiliaryTypes;
}
@
Override
public
Map<
TypeDescription,
File>
saveIn(
File folder) throws
IOException {
Map<
TypeDescription,
File>
savedFiles = new
HashMap<
TypeDescription,
File>();
File target = new
File(
folder,
typeDescription.
getName().
replace('.',
File.
separatorChar) +
CLASS_FILE_EXTENSION);
if (
target.
getParentFile() != null && !
target.
getParentFile().
isDirectory() && !
target.
getParentFile().
mkdirs()) {
throw new
IllegalArgumentException("Could not create directory: " +
target.
getParentFile());
}
OutputStream outputStream = new
FileOutputStream(
target);
try {
outputStream.
write(
binaryRepresentation);
} finally {
outputStream.
close();
}
savedFiles.
put(
typeDescription,
target);
for (
DynamicType auxiliaryType :
auxiliaryTypes) {
savedFiles.
putAll(
auxiliaryType.
saveIn(
folder));
}
return
savedFiles;
}
@
Override
public
File inject(
File sourceJar,
File targetJar) throws
IOException {
JarInputStream jarInputStream = new
JarInputStream(new
BufferedInputStream(new
FileInputStream(
sourceJar)));
try {
if (!
targetJar.
isFile() && !
targetJar.
createNewFile()) {
throw new
IllegalArgumentException("Could not create file: " +
targetJar);
}
Manifest manifest =
jarInputStream.
getManifest();
JarOutputStream jarOutputStream =
manifest == null
? new
JarOutputStream(new
FileOutputStream(
targetJar))
: new
JarOutputStream(new
FileOutputStream(
targetJar),
manifest);
try {
Map<
TypeDescription, byte[]>
rawAuxiliaryTypes =
getAuxiliaryTypes();
Map<
String, byte[]>
files = new
HashMap<
String, byte[]>();
for (
Map.
Entry<
TypeDescription, byte[]>
entry :
rawAuxiliaryTypes.
entrySet()) {
files.
put(
entry.
getKey().
getInternalName() +
CLASS_FILE_EXTENSION,
entry.
getValue());
}
files.
put(
typeDescription.
getInternalName() +
CLASS_FILE_EXTENSION,
binaryRepresentation);
JarEntry jarEntry;
while ((
jarEntry =
jarInputStream.
getNextJarEntry()) != null) {
byte[]
replacement =
files.
remove(
jarEntry.
getName());
if (
replacement == null) {
jarOutputStream.
putNextEntry(
jarEntry);
byte[]
buffer = new byte[
BUFFER_SIZE];
int
index;
while ((
index =
jarInputStream.
read(
buffer)) !=
END_OF_FILE) {
jarOutputStream.
write(
buffer,
FROM_BEGINNING,
index);
}
} else {
jarOutputStream.
putNextEntry(new
JarEntry(
jarEntry.
getName()));
jarOutputStream.
write(
replacement);
}
jarInputStream.
closeEntry();
jarOutputStream.
closeEntry();
}
for (
Map.
Entry<
String, byte[]>
entry :
files.
entrySet()) {
jarOutputStream.
putNextEntry(new
JarEntry(
entry.
getKey()));
jarOutputStream.
write(
entry.
getValue());
jarOutputStream.
closeEntry();
}
} finally {
jarOutputStream.
close();
}
} finally {
jarInputStream.
close();
}
return
targetJar;
}
@
Override
public
File inject(
File jar) throws
IOException {
File temporary =
inject(
jar,
File.
createTempFile(
jar.
getName(),
TEMP_SUFFIX));
try {
InputStream jarInputStream = new
BufferedInputStream(new
FileInputStream(
temporary));
try {
OutputStream jarOutputStream = new
BufferedOutputStream(new
FileOutputStream(
jar));
try {
byte[]
buffer = new byte[
BUFFER_SIZE];
int
index;
while ((
index =
jarInputStream.
read(
buffer)) !=
END_OF_FILE) {
jarOutputStream.
write(
buffer,
FROM_BEGINNING,
index);
}
} finally {
jarOutputStream.
close();
}
} finally {
jarInputStream.
close();
}
} finally {
if (!
temporary.
delete()) {
temporary.
deleteOnExit();
}
}
return
jar;
}
@
Override
public
File toJar(
File file) throws
IOException {
Manifest manifest = new
Manifest();
manifest.
getMainAttributes().
put(
Attributes.
Name.
MANIFEST_VERSION,
MANIFEST_VERSION);
return
toJar(
file,
manifest);
}
@
Override
public
File toJar(
File file,
Manifest manifest) throws
IOException {
if (!
file.
isFile() && !
file.
createNewFile()) {
throw new
IllegalArgumentException("Could not create file: " +
file);
}
JarOutputStream outputStream = new
JarOutputStream(new
FileOutputStream(
file),
manifest);
try {
for (
Map.
Entry<
TypeDescription, byte[]>
entry :
getAuxiliaryTypes().
entrySet()) {
outputStream.
putNextEntry(new
JarEntry(
entry.
getKey().
getInternalName() +
CLASS_FILE_EXTENSION));
outputStream.
write(
entry.
getValue());
outputStream.
closeEntry();
}
outputStream.
putNextEntry(new
JarEntry(
typeDescription.
getInternalName() +
CLASS_FILE_EXTENSION));
outputStream.
write(
binaryRepresentation);
outputStream.
closeEntry();
} finally {
outputStream.
close();
}
return
file;
}
/**
* A default implementation of an unloaded dynamic type.
*
* @param <T> The most specific known loaded type that is implemented by this dynamic type, usually the
* type itself, an interface or the direct super class.
*/
@
HashCodeAndEqualsPlugin.
Enhance
public static class
Unloaded<T> extends
Default implements
DynamicType.
Unloaded<T> {
/**
* The type resolution strategy to use for initializing the dynamic type.
*/
private final
TypeResolutionStrategy.
Resolved typeResolutionStrategy;
/**
* Creates a new unloaded representation of a dynamic type.
*
* @param typeDescription A description of this dynamic type.
* @param binaryRepresentation An array of byte of the binary representation of this dynamic type.
* @param loadedTypeInitializer The type initializer of this dynamic type.
* @param auxiliaryTypes The auxiliary types that are required for this dynamic type.
* @param typeResolutionStrategy The type resolution strategy to use for initializing the dynamic type.
*/
public
Unloaded(
TypeDescription typeDescription,
byte[]
binaryRepresentation,
LoadedTypeInitializer loadedTypeInitializer,
List<? extends
DynamicType>
auxiliaryTypes,
TypeResolutionStrategy.
Resolved typeResolutionStrategy) {
super(
typeDescription,
binaryRepresentation,
loadedTypeInitializer,
auxiliaryTypes);
this.
typeResolutionStrategy =
typeResolutionStrategy;
}
@
Override
public
DynamicType.
Loaded<T>
load(
ClassLoader classLoader) {
return
classLoader instanceof
InjectionClassLoader && !((
InjectionClassLoader)
classLoader).
isSealed()
?
load((
InjectionClassLoader)
classLoader,
InjectionClassLoader.
Strategy.
INSTANCE)
:
load(
classLoader,
ClassLoadingStrategy.
Default.
WRAPPER);
}
@
Override
public <S extends
ClassLoader>
DynamicType.
Loaded<T>
load(S
classLoader,
ClassLoadingStrategy<? super S>
classLoadingStrategy) {
return new
Default.
Loaded<T>(
typeDescription,
binaryRepresentation,
loadedTypeInitializer,
auxiliaryTypes,
typeResolutionStrategy.
initialize(this,
classLoader,
classLoadingStrategy));
}
@
Override
public
DynamicType.
Unloaded<T>
include(
DynamicType...
dynamicType) {
return
include(
Arrays.
asList(
dynamicType));
}
@
Override
public
DynamicType.
Unloaded<T>
include(
List<? extends
DynamicType>
dynamicType) {
return new
Default.
Unloaded<T>(
typeDescription,
binaryRepresentation,
loadedTypeInitializer,
CompoundList.
of(
auxiliaryTypes,
dynamicType),
typeResolutionStrategy);
}
}
/**
* A default implementation of a loaded dynamic type.
*
* @param <T> The most specific known loaded type that is implemented by this dynamic type, usually the
* type itself, an interface or the direct super class.
*/
@
HashCodeAndEqualsPlugin.
Enhance
protected static class
Loaded<T> extends
Default implements
DynamicType.
Loaded<T> {
/**
* The loaded types for the given loaded dynamic type.
*/
private final
Map<
TypeDescription,
Class<?>>
loadedTypes;
/**
* Creates a new representation of a loaded dynamic type.
*
* @param typeDescription A description of this dynamic type.
* @param typeByte An array of byte of the binary representation of this dynamic type.
* @param loadedTypeInitializer The type initializer of this dynamic type.
* @param auxiliaryTypes The auxiliary types that are required for this dynamic type.
* @param loadedTypes A map of loaded types for this dynamic type and all its auxiliary types.
*/
protected
Loaded(
TypeDescription typeDescription,
byte[]
typeByte,
LoadedTypeInitializer loadedTypeInitializer,
List<? extends
DynamicType>
auxiliaryTypes,
Map<
TypeDescription,
Class<?>>
loadedTypes) {
super(
typeDescription,
typeByte,
loadedTypeInitializer,
auxiliaryTypes);
this.
loadedTypes =
loadedTypes;
}
@
Override
@
SuppressWarnings("unchecked")
public
Class<? extends T>
getLoaded() {
return (
Class<? extends T>)
loadedTypes.
get(
typeDescription);
}
@
Override
public
Map<
TypeDescription,
Class<?>>
getLoadedAuxiliaryTypes() {
Map<
TypeDescription,
Class<?>>
loadedAuxiliaryTypes = new
HashMap<
TypeDescription,
Class<?>>(
loadedTypes);
loadedAuxiliaryTypes.
remove(
typeDescription);
return
loadedAuxiliaryTypes;
}
}
}
}