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

org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.DynamicType Maven / Gradle / Ivy

There is a newer version: 9.2.0
Show newest version
package org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.ClassFileVersion;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.asm.AsmVisitorWrapper;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.build.HashCodeAndEqualsPlugin;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.annotation.AnnotationDescription;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.annotation.AnnotationList;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.annotation.AnnotationValue;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.field.FieldDescription;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.method.MethodDescription;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.method.ParameterDescription;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.method.ParameterList;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.modifier.*;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.type.TypeDefinition;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.type.TypeDescription;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.type.TypeList;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.description.type.TypeVariableToken;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.loading.InjectionClassLoader;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.scaffold.*;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.*;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.attribute.*;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.auxiliary.AuxiliaryType;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.matcher.LatentMatcher;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.pool.TypePool;
import org.apache.skywalking.apm.dependencies.net.bytebuddy.utility.CompoundList;

import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.jar.*;

import static org.apache.skywalking.apm.dependencies.net.bytebuddy.matcher.ElementMatchers.*;

/**
 * A dynamic type that is created at runtime, usually as the result of applying a
 * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.DynamicType.Builder} or as the result of an
 * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.auxiliary.AuxiliaryType}.
 * 

 

* 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 { /** *

* Returns a description of this dynamic type. *

*

* Note: 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. *

* * @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(); /** *

* Returns a map of all auxiliary types that are required for making use of the main type. *

*

* Note: 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. *

* * @return A map of all auxiliary types by their descriptions to their binary representation. */ Map 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 getAllTypes(); /** *

* Returns a map of all loaded type initializers for the main type and all auxiliary types, if any. *

*

* Note: 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. *

* * @return A mapping of all types' descriptions to their loaded type initializers. */ Map 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(); /** *

* 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. *

*

* Note: 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. *

* * @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 saveIn(File folder) throws IOException; /** * Injects the types of this dynamic type into a given jar file. Any pre-existent type with the same name * is overridden during injection. The resulting jar is going to be a recreation of the original jar and not a * patched version with a new central directory. No directory entries are added to the generated jar. * * @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 jar file. Any pre-existent type with the same name * is overridden during injection. The resulting jar is going to be a recreation of the original jar and not a * patched version with a new central directory. No directory entries are added to the generated jar. * * @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 jar 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. No directory entries are added to the generated jar. * * @param file The target file to which the jar 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 jar file. The folder of the given {@code file} must * exist prior to calling this method. No directory entries are added to the generated jar. * * @param file The target file to which the jar is written to. * @param manifest The manifest of the created jar. * @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 A loaded type that the built type is guaranteed to be a subclass of. */ interface Builder { /** * Applies the supplied {@link AsmVisitorWrapper} onto the {@link org.apache.skywalking.apm.dependencies.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 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 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 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 modifiers(Collection 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 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 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 merge(Collection modifierContributors); /** *

* Defines this type as a top-level type that is not declared by another type or enclosed by another member. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @return A new builder that is equal to this builder but without any declaration of a a declared or enclosed type. */ Builder topLevelType(); /** *

* Defines this type as an inner type of the supplied type. Without any additional configuration, the type declaration is defined * as a local type. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 innerTypeOf(Class type); /** *

* Defines this type as an inner type of the supplied type. Without any additional configuration, the type declaration is * defined as a local type. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 innerTypeOf(TypeDescription type); /** *

* 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. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 innerTypeOf(Method method); /** *

* 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. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 innerTypeOf(Constructor constructor); /** *

* 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. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 innerTypeOf(MethodDescription.InDefinedShape methodDescription); /** *

* 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. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 declaredTypes(Class... type); /** *

* 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. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 declaredTypes(TypeDescription... type); /** *

* 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. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 declaredTypes(List> types); /** *

* 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. *

*

* Important: Changing the declaration hierarchy of a type has no influence on the nest mate hierarchy. *

*

* Warning: 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. *

* * @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 declaredTypes(Collection types); /** *

* Defines this type as self-hosted, i.e. as only being a nest mate of itself. *

*

* Important: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy. *

*

* Warning: 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. *

* * @return A new builder that is equal to this builder but where the built type is a self-hosted nest mate. */ Builder noNestMate(); /** *

* Defines this type as a nest member of the supplied type as a nest host. *

*

* Important: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy. *

*

* Warning: 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. *

* * @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 nestHost(Class type); /** *

* Defines this type as a nest member of the supplied type as a nest host. *

*

* Important: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy. *

*

* Warning: 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. *

* * @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 nestHost(TypeDescription type); /** *

* Defines this type as a nest host for the supplied types. *

*

* Important: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy. *

*

* Warning: 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. *

* * @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 nestMembers(Class... type); /** *

* Defines this type as a nest host for the supplied types. *

*

* Important: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy. *

*

* Warning: 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. *

* * @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 nestMembers(TypeDescription... type); /** *

* Defines this type as a nest host for the supplied types. *

*

* Important: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy. *

*

* Warning: 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. *

* * @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 nestMembers(List> types); /** *

* Defines this type as a nest host for the supplied types. *

*

* Important: Changing the nest mate hierarchy of a type has no influence on the declaration hierarchy. *

*

* Warning: 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. *

* * @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 nestMembers(Collection 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 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 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 annotateType(List 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 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 annotateType(Collection annotations); /** *

* 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. *

*

* Note: This methods implements the supplied types as is, i.e. any {@link Class} values are implemented * as raw types if they declare type variables or an owner type. *

* * @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 implement(Type... interfaceType); /** *

* 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. *

*

* Note: This methods implements the supplied types as is, i.e. any {@link Class} values are implemented * as raw types if they declare type variables or an owner type. *

* * @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 implement(List interfaceTypes); /** *

* 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. *

*

* Note: This methods implements the supplied types as is, i.e. any {@link TypeDescription} values are * implemented as raw types if they declare type variables or an owner type. *

* * @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 implement(TypeDefinition... interfaceType); /** *

* 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. *

*

* Note: This methods implements the supplied types as is, i.e. any {@link TypeDescription} values are * implemented as raw types if they declare type variables or an owner type. *

* * @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 implement(Collection interfaceTypes); /** *

* Executes the supplied byte code appender within the beginning of the instrumented type's type initializer. The * supplied byte code appender must not return from the method. If several byte code appenders are supplied, * they are executed within their application order. *

*

* 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 org.apache.skywalking.apm.dependencies.net.bytebuddy.matcher.ElementMatchers#isTypeInitializer()} matcher. *

* * @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 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 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 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 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 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 require(Collection 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 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 typeVariable(String symbol, List 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 typeVariable(String symbol, Collection 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 transform(ElementMatcher matcher, Transformer 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 defineField(String name, Type type, Collection 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 defineField(String name, TypeDefinition type, Collection 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 org.apache.skywalking.apm.dependencies.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 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 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 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 serialVersionUid(long serialVersionUid); /** *

* 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. *

*

* When a type is redefined or rebased, any annotations that the field declared previously is preserved * as it is if Byte Buddy is configured to retain such annotations by * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be * altered, annotation retention must be disabled. *

*

* 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. *

* * @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 field(ElementMatcher matcher); /** *

* 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. *

*

* When a type is redefined or rebased, any annotations that the field declared previously is preserved * as it is if Byte Buddy is configured to retain such annotations by * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be * altered, annotation retention must be disabled. *

*

* 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. *

* * @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 field(LatentMatcher matcher); /** *

* 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. *

*

* 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. *

* * @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 ignoreAlso(ElementMatcher ignoredMethods); /** *

* 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. *

*

* 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. *

* * @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 ignoreAlso(LatentMatcher 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 defineMethod(String name, Type returnType, Collection 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 defineMethod(String name, TypeDefinition returnType, Collection 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 org.apache.skywalking.apm.dependencies.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 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 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 defineConstructor(Collection 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 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 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 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 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 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 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 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 defineProperty(String name, TypeDefinition type, boolean readOnly); /** *

* 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. *

*

* When a type is redefined or rebased, any annotations that the method declared previously is preserved * as it is if Byte Buddy is configured to retain such annotations by * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be * altered, annotation retention must be disabled. *

*

* 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. *

*

* Note that the specified definition does never apply for methods that are explicitly ignored. *

* * @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 method(ElementMatcher matcher); /** *

* 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. *

*

* When a type is redefined or rebased, any annotations that the constructor declared previously is preserved * as it is if Byte Buddy is configured to retain such annotations by * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be * altered, annotation retention must be disabled. *

*

* 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. *

*

* Note that the specified definition does never apply for methods that are explicitly ignored. *

* * @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 constructor(ElementMatcher matcher); /** *

* 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. *

*

* When a type is redefined or rebased, any annotations that the method or constructor declared previously is preserved * as it is if Byte Buddy is configured to retain such annotations by * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be * altered, annotation retention must be disabled. *

*

* 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. *

*

* Note that the specified definition does never apply for methods that are explicitly ignored. *

*

* Important: It is possible to instrument the dynamic type's initializer. Depending on the used {@link TypeResolutionStrategy}, * the type initializer might be run before 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. *

* * @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 invokable(ElementMatcher matcher); /** *

* 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. *

*

* When a type is redefined or rebased, any annotations that the method or constructor declared previously is preserved * as it is if Byte Buddy is configured to retain such annotations by * {@link org.apache.skywalking.apm.dependencies.net.bytebuddy.implementation.attribute.AnnotationRetention#ENABLED}. If any existing annotations should be * altered, annotation retention must be disabled. *

*

* 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. *

*

* Note that the specified definition does never apply for methods that are explicitly ignored. *

*

* Important: It is possible to instrument the dynamic type's initializer. Depending on the used {@link TypeResolutionStrategy}, * the type initializer might be run before 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. *

* * @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 invokable(LatentMatcher 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 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 withToString(); /** *

* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown. *

*

* 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. *

*

* 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. *

* * @return An unloaded dynamic type representing the type specified by this builder. */ DynamicType.Unloaded make(); /** *

* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown. *

*

* 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. *

* * @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 make(TypeResolutionStrategy typeResolutionStrategy); /** *

* Creates the dynamic type this builder represents. If the specified dynamic type is not legal, an {@link IllegalStateException} is thrown. *

*

* 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. *

* * @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 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 make(TypeResolutionStrategy typeResolutionStrategy, TypePool typePool); /** * An inner type definition for defining a type that is contained within another type, method or constructor. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface InnerTypeDefinition extends Builder { /** * 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 asAnonymousType(); /** * An inner type definition for defining a type that is contained within another type. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface ForType extends InnerTypeDefinition { /** * 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 asMemberType(); } } /** * A builder for a type variable definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface TypeVariableDefinition extends Builder { /** * 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 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 annotateTypeVariable(List 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 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 annotateTypeVariable(Collection annotations); /** * An abstract base implementation of a type variable definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends Builder.AbstractBase.Delegator implements TypeVariableDefinition { /** * {@inheritDoc} */ public TypeVariableDefinition annotateTypeVariable(Annotation... annotation) { return annotateTypeVariable(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public TypeVariableDefinition annotateTypeVariable(List annotations) { return annotateTypeVariable(new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public TypeVariableDefinition annotateTypeVariable(AnnotationDescription... annotation) { return annotateTypeVariable(Arrays.asList(annotation)); } } } /** * A builder for a field definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface FieldDefinition { /** * 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 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 annotateField(List 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 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 annotateField(Collection 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 attribute(FieldAttributeAppender.Factory fieldAttributeAppenderFactory); /** * Applies the supplied transformer onto the previously defined or matched field. The transformed * field is written as it is 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 transform(Transformer transformer); /** * A builder for a field definition that allows for defining a value. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Valuable extends FieldDefinition { /** *

* 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}. *

*

* Important: 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. *

* * @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 value(boolean value); /** *

* 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}. *

*

* Important: 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. *

* * @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 value(int value); /** *

* Defines the supplied {@code long} value as a default value of the previously defined or matched field. *

*

* Important: 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. *

* * @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 value(long value); /** *

* Defines the supplied {@code float} value as a default value of the previously defined or matched field. *

*

* Important: 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. *

* * @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 value(float value); /** *

* Defines the supplied {@code double} value as a default value of the previously defined or matched field. *

*

* Important: 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. *

* * @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 value(double value); /** *

* Defines the supplied {@link String} value as a default value of the previously defined or matched field. *

*

* Important: 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. *

* * @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 value(String value); } /** * A builder for an optional field definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Optional extends FieldDefinition, Builder { /** * A builder for an optional field definition that allows for defining a value. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Valuable extends FieldDefinition.Valuable, Optional { /** * An abstract base implementation of an optional field definition that allows for defining a value. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends Optional.AbstractBase implements Optional.Valuable { /** * {@inheritDoc} */ public FieldDefinition.Optional value(boolean value) { return defaultValue(value ? 1 : 0); } /** * {@inheritDoc} */ public FieldDefinition.Optional value(int value) { return defaultValue(value); } /** * {@inheritDoc} */ public FieldDefinition.Optional value(long value) { return defaultValue(value); } /** * {@inheritDoc} */ public FieldDefinition.Optional value(float value) { return defaultValue(value); } /** * {@inheritDoc} */ public FieldDefinition.Optional value(double value) { return defaultValue(value); } /** * {@inheritDoc} */ public FieldDefinition.Optional 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 defaultValue(Object defaultValue); /** * An adapter for an optional field definition that allows for defining a value. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ @HashCodeAndEqualsPlugin.Enhance private abstract static class Adapter extends Optional.Valuable.AbstractBase { /** * The field attribute appender factory to apply. */ protected final FieldAttributeAppender.Factory fieldAttributeAppenderFactory; /** * The field transformer to apply. */ protected final Transformer 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 transformer, Object defaultValue) { this.fieldAttributeAppenderFactory = fieldAttributeAppenderFactory; this.transformer = transformer; this.defaultValue = defaultValue; } /** * {@inheritDoc} */ public FieldDefinition.Optional attribute(FieldAttributeAppender.Factory fieldAttributeAppenderFactory) { return materialize(new FieldAttributeAppender.Factory.Compound(this.fieldAttributeAppenderFactory, fieldAttributeAppenderFactory), transformer, defaultValue); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") // In absence of @SafeVarargs public FieldDefinition.Optional transform(Transformer transformer) { return materialize(fieldAttributeAppenderFactory, new Transformer.Compound(this.transformer, transformer), defaultValue); } @Override protected FieldDefinition.Optional 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 materialize(FieldAttributeAppender.Factory fieldAttributeAppenderFactory, Transformer transformer, Object defaultValue); } } } /** * An abstract base implementation for an optional field definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends Builder.AbstractBase.Delegator implements FieldDefinition.Optional { /** * {@inheritDoc} */ public FieldDefinition.Optional annotateField(Annotation... annotation) { return annotateField(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public FieldDefinition.Optional annotateField(List annotations) { return annotateField(new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public FieldDefinition.Optional annotateField(AnnotationDescription... annotation) { return annotateField(Arrays.asList(annotation)); } } } } /** * A builder for a method definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface MethodDefinition extends Builder { /** * 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 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 annotateMethod(List 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 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 annotateMethod(Collection 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 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 annotateParameter(int index, List 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 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 annotateParameter(int index, Collection 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 attribute(MethodAttributeAppender.Factory methodAttributeAppenderFactory); /** * Applies the supplied transformer onto the previously defined or matched method. The transformed * method is written as it is 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 transform(Transformer transformer); /** * A builder for a method definition with a receiver type. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface ReceiverTypeDefinition extends MethodDefinition { /** * 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 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 receiverType(TypeDescription.Generic receiverType); /** * An abstract base implementation of a method definition that can accept a receiver type. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends MethodDefinition.AbstractBase implements ReceiverTypeDefinition { /** * {@inheritDoc} */ public MethodDefinition receiverType(AnnotatedElement receiverType) { return receiverType(TypeDescription.Generic.AnnotationReader.DISPATCHER.resolve(receiverType)); } } } /** * A builder for defining an implementation of a method. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface ImplementationDefinition { /** * Implements the previously defined or matched method by the supplied implementation. A method interception * is typically implemented in one of the following ways: *
    *
  1. 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.
  2. *
  3. 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.
  4. *
  5. If a virtual method is inherited from a super type, it is overridden. The overridden method is available * for super method invocation.
  6. *
* * @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 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 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 org.apache.skywalking.apm.dependencies.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 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 The type of the annotation property. * @return A builder where the previously defined or matched method is implemented to return an annotation default value. */ MethodDefinition.ReceiverTypeDefinition defaultValue(W value, Class type); /** * A builder for optionally defining an implementation of a method. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Optional extends ImplementationDefinition, Builder { /* union type */ } /** * An abstract base implementation for a builder optionally defining an implementation of a method. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase implements ImplementationDefinition { /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(W value, Class type) { return defaultValue(AnnotationDescription.ForLoadedAnnotation.asValue(value, type)); } } } /** * A builder for defining an implementation of a method and optionally defining a type variable. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface TypeVariableDefinition extends ImplementationDefinition { /** * 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 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 typeVariable(String symbol, List 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 typeVariable(String symbol, Collection bounds); /** * A builder for optionally defining an annotation for a type variable. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Annotatable extends TypeVariableDefinition { /** * 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 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 annotateTypeVariable(List 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 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 annotateTypeVariable(Collection annotations); /** * An abstract base implementation for defining an annotation on a parameter. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends TypeVariableDefinition.AbstractBase implements Annotatable { /** * {@inheritDoc} */ public TypeVariableDefinition.Annotatable annotateTypeVariable(Annotation... annotation) { return annotateTypeVariable(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public TypeVariableDefinition.Annotatable annotateTypeVariable(List annotations) { return annotateTypeVariable(new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public TypeVariableDefinition.Annotatable annotateTypeVariable(AnnotationDescription... annotation) { return annotateTypeVariable(Arrays.asList(annotation)); } /** * An adapter implementation for an annotatable type variable definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ protected abstract static class Adapter extends TypeVariableDefinition.Annotatable.AbstractBase { /** * {@inheritDoc} */ public TypeVariableDefinition.Annotatable typeVariable(String symbol, Collection bounds) { return materialize().typeVariable(symbol, bounds); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition intercept(Implementation implementation) { return materialize().intercept(implementation); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition withoutCode() { return materialize().withoutCode(); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(AnnotationValue annotationValue) { return materialize().defaultValue(annotationValue); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(V value, Class 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 materialize(); } } } /** * An abstract base implementation for defining an implementation of a method and optionally defining a type variable. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends ImplementationDefinition.AbstractBase implements TypeVariableDefinition { /** * {@inheritDoc} */ public Annotatable typeVariable(String symbol) { return typeVariable(symbol, Collections.singletonList(Object.class)); } /** * {@inheritDoc} */ public Annotatable typeVariable(String symbol, Type... bound) { return typeVariable(symbol, Arrays.asList(bound)); } /** * {@inheritDoc} */ public Annotatable typeVariable(String symbol, List bounds) { return typeVariable(symbol, new TypeList.Generic.ForLoadedTypes(bounds)); } /** * {@inheritDoc} */ public Annotatable 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 A loaded type that the built type is guaranteed to be a subclass of. */ interface ExceptionDefinition extends TypeVariableDefinition { /** * 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 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 throwing(List 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 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 throwing(Collection types); /** * An abstract base implementation for defining an implementation of a method and optionally defining a type variable or thrown exception. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends TypeVariableDefinition.AbstractBase implements ExceptionDefinition { /** * {@inheritDoc} */ public ExceptionDefinition throwing(Type... type) { return throwing(Arrays.asList(type)); } /** * {@inheritDoc} */ public ExceptionDefinition throwing(List types) { return throwing(new TypeList.Generic.ForLoadedTypes(types)); } /** * {@inheritDoc} */ public ExceptionDefinition 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 A loaded type that the built type is guaranteed to be a subclass of. */ interface ParameterDefinition extends ExceptionDefinition { /** * 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 withParameter(Type type, String name, Collection 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 withParameter(TypeDefinition type, String name, Collection 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 org.apache.skywalking.apm.dependencies.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 withParameter(TypeDefinition type, String name, int modifiers); /** * A builder for optionally defining an annotation on a parameter. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Annotatable extends ParameterDefinition { /** * 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 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 annotateParameter(List 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 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 annotateParameter(Collection annotations); /** * An abstract base implementation for defining an annotation on a parameter. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends ParameterDefinition.AbstractBase implements Annotatable { /** * {@inheritDoc} */ public ParameterDefinition.Annotatable annotateParameter(Annotation... annotation) { return annotateParameter(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public ParameterDefinition.Annotatable annotateParameter(List annotations) { return annotateParameter(new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public ParameterDefinition.Annotatable annotateParameter(AnnotationDescription... annotation) { return annotateParameter(Arrays.asList(annotation)); } /** * An adapter implementation for defining an annotation on a parameter. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ protected abstract static class Adapter extends ParameterDefinition.Annotatable.AbstractBase { /** * {@inheritDoc} */ public ParameterDefinition.Annotatable withParameter(TypeDefinition type, String name, int modifiers) { return materialize().withParameter(type, name, modifiers); } /** * {@inheritDoc} */ public ExceptionDefinition throwing(Collection types) { return materialize().throwing(types); } /** * {@inheritDoc} */ public TypeVariableDefinition.Annotatable typeVariable(String symbol, Collection bounds) { return materialize().typeVariable(symbol, bounds); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition intercept(Implementation implementation) { return materialize().intercept(implementation); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition withoutCode() { return materialize().withoutCode(); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(AnnotationValue annotationValue) { return materialize().defaultValue(annotationValue); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(V value, Class 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 materialize(); } } } /** * A builder for defining an implementation of a method and optionally defining a type variable, thrown exception or a parameter type. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Simple extends ExceptionDefinition { /** * 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 org.apache.skywalking.apm.dependencies.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 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 org.apache.skywalking.apm.dependencies.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 withParameter(TypeDefinition type); /** * A builder for optionally defining an annotation on a parameter. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ interface Annotatable extends Simple { /** * 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 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 annotateParameter(List 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 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 annotateParameter(Collection annotations); /** * An abstract base implementation of a simple parameter definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends Simple.AbstractBase implements Annotatable { /** * {@inheritDoc} */ public Simple.Annotatable annotateParameter(Annotation... annotation) { return annotateParameter(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public Simple.Annotatable annotateParameter(List annotations) { return annotateParameter(new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public Simple.Annotatable annotateParameter(AnnotationDescription... annotation) { return annotateParameter(Arrays.asList(annotation)); } /** * An adapter implementation of a simple parameter definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ protected abstract static class Adapter extends Simple.Annotatable.AbstractBase { /** * {@inheritDoc} */ public Simple.Annotatable withParameter(TypeDefinition type) { return materialize().withParameter(type); } /** * {@inheritDoc} */ public ExceptionDefinition throwing(Collection types) { return materialize().throwing(types); } /** * {@inheritDoc} */ public TypeVariableDefinition.Annotatable typeVariable(String symbol, Collection bounds) { return materialize().typeVariable(symbol, bounds); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition intercept(Implementation implementation) { return materialize().intercept(implementation); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition withoutCode() { return materialize().withoutCode(); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(AnnotationValue annotationValue) { return materialize().defaultValue(annotationValue); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(V value, Class 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 materialize(); } } } /** * An abstract base implementation of an exception definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends ExceptionDefinition.AbstractBase implements Simple { /** * {@inheritDoc} */ public Simple.Annotatable 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 one-by-one 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 A loaded type that the built type is guaranteed to be a subclass of. */ interface Initial extends ParameterDefinition, Simple { /** * Defines the specified parameters for the currently defined method. * * @param type The parameter types. Any type can also be {@link org.apache.skywalking.apm.dependencies.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 withParameters(Type... type); /** * Defines the specified parameters for the currently defined method. * * @param types The parameter types. Any type can also be {@link org.apache.skywalking.apm.dependencies.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 withParameters(List types); /** * Defines the specified parameters for the currently defined method. * * @param type The parameter types. Any type can also be {@link org.apache.skywalking.apm.dependencies.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 withParameters(TypeDefinition... type); /** * Defines the specified parameters for the currently defined method. * * @param types The parameter types. Any type can also be {@link org.apache.skywalking.apm.dependencies.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 withParameters(Collection types); /** * An abstract base implementation for an initial parameter definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends ParameterDefinition.AbstractBase implements Initial { /** * {@inheritDoc} */ public Simple.Annotatable withParameter(Type type) { return withParameter(TypeDefinition.Sort.describe(type)); } /** * {@inheritDoc} */ public ExceptionDefinition withParameters(Type... type) { return withParameters(Arrays.asList(type)); } /** * {@inheritDoc} */ public ExceptionDefinition withParameters(List types) { return withParameters(new TypeList.Generic.ForLoadedTypes(types)); } /** * {@inheritDoc} */ public ExceptionDefinition withParameters(TypeDefinition... type) { return withParameters(Arrays.asList(type)); } /** * {@inheritDoc} */ public ExceptionDefinition withParameters(Collection types) { ParameterDefinition.Simple 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 A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends ExceptionDefinition.AbstractBase implements ParameterDefinition { /** * {@inheritDoc} */ public ParameterDefinition.Annotatable withParameter(Type type, String name, ModifierContributor.ForParameter... modifierContributor) { return withParameter(type, name, Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public ParameterDefinition.Annotatable withParameter(Type type, String name, Collection modifierContributors) { return withParameter(type, name, ModifierContributor.Resolver.of(modifierContributors).resolve()); } /** * {@inheritDoc} */ public ParameterDefinition.Annotatable withParameter(Type type, String name, int modifiers) { return withParameter(TypeDefinition.Sort.describe(type), name, modifiers); } /** * {@inheritDoc} */ public ParameterDefinition.Annotatable withParameter(TypeDefinition type, String name, ModifierContributor.ForParameter... modifierContributor) { return withParameter(type, name, Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public ParameterDefinition.Annotatable withParameter(TypeDefinition type, String name, Collection modifierContributors) { return withParameter(type, name, ModifierContributor.Resolver.of(modifierContributors).resolve()); } } } /** * An abstract base implementation of a method definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase extends Builder.AbstractBase.Delegator implements MethodDefinition { /** * {@inheritDoc} */ public MethodDefinition annotateMethod(Annotation... annotation) { return annotateMethod(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public MethodDefinition annotateMethod(List annotations) { return annotateMethod(new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public MethodDefinition annotateMethod(AnnotationDescription... annotation) { return annotateMethod(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public MethodDefinition annotateParameter(int index, Annotation... annotation) { return annotateParameter(index, Arrays.asList(annotation)); } /** * {@inheritDoc} */ public MethodDefinition annotateParameter(int index, List annotations) { return annotateParameter(index, new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public MethodDefinition annotateParameter(int index, AnnotationDescription... annotation) { return annotateParameter(index, Arrays.asList(annotation)); } /** * An adapter implementation of a method definition. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ @HashCodeAndEqualsPlugin.Enhance protected abstract static class Adapter extends MethodDefinition.ReceiverTypeDefinition.AbstractBase { /** * 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 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 transformer) { this.handler = handler; this.methodAttributeAppenderFactory = methodAttributeAppenderFactory; this.transformer = transformer; } /** * {@inheritDoc} */ public MethodDefinition attribute(MethodAttributeAppender.Factory methodAttributeAppenderFactory) { return materialize(handler, new MethodAttributeAppender.Factory.Compound(this.methodAttributeAppenderFactory, methodAttributeAppenderFactory), transformer); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") // In absence of @SafeVarargs public MethodDefinition transform(Transformer transformer) { return materialize(handler, methodAttributeAppenderFactory, new Transformer.Compound(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 materialize(MethodRegistry.Handler handler, MethodAttributeAppender.Factory methodAttributeAppenderFactory, Transformer transformer); } } } /** * An abstract base implementation of a dynamic type builder. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ abstract class AbstractBase implements Builder { /** * {@inheritDoc} */ public InnerTypeDefinition.ForType innerTypeOf(Class type) { return innerTypeOf(TypeDescription.ForLoadedType.of(type)); } /** * {@inheritDoc} */ public InnerTypeDefinition innerTypeOf(Method method) { return innerTypeOf(new MethodDescription.ForLoadedMethod(method)); } /** * {@inheritDoc} */ public InnerTypeDefinition innerTypeOf(Constructor constructor) { return innerTypeOf(new MethodDescription.ForLoadedConstructor(constructor)); } /** * {@inheritDoc} */ public Builder declaredTypes(Class... type) { return declaredTypes(Arrays.asList(type)); } /** * {@inheritDoc} */ public Builder declaredTypes(TypeDescription... type) { return declaredTypes(Arrays.asList(type)); } /** * {@inheritDoc} */ public Builder declaredTypes(List> type) { return declaredTypes(new TypeList.ForLoadedTypes(type)); } /** * {@inheritDoc} */ public Builder noNestMate() { return nestHost(TargetType.DESCRIPTION); } /** * {@inheritDoc} */ public Builder nestHost(Class type) { return nestHost(TypeDescription.ForLoadedType.of(type)); } /** * {@inheritDoc} */ public Builder nestMembers(Class... type) { return nestMembers(Arrays.asList(type)); } /** * {@inheritDoc} */ public Builder nestMembers(TypeDescription... type) { return nestMembers(Arrays.asList(type)); } /** * {@inheritDoc} */ public Builder nestMembers(List> types) { return nestMembers(new TypeList.ForLoadedTypes(types)); } /** * {@inheritDoc} */ public Builder annotateType(Annotation... annotation) { return annotateType(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public Builder annotateType(List annotations) { return annotateType(new AnnotationList.ForLoadedAnnotations(annotations)); } /** * {@inheritDoc} */ public Builder annotateType(AnnotationDescription... annotation) { return annotateType(Arrays.asList(annotation)); } /** * {@inheritDoc} */ public Builder modifiers(ModifierContributor.ForType... modifierContributor) { return modifiers(Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public Builder modifiers(Collection modifierContributors) { return modifiers(ModifierContributor.Resolver.of(modifierContributors).resolve()); } /** * {@inheritDoc} */ public Builder merge(ModifierContributor.ForType... modifierContributor) { return merge(Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition.Optional implement(Type... interfaceType) { return implement(Arrays.asList(interfaceType)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition.Optional implement(List interfaceTypes) { return implement(new TypeList.Generic.ForLoadedTypes(interfaceTypes)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition.Optional implement(TypeDefinition... interfaceType) { return implement(Arrays.asList(interfaceType)); } /** * {@inheritDoc} */ public TypeVariableDefinition typeVariable(String symbol) { return typeVariable(symbol, TypeDescription.Generic.OBJECT); } /** * {@inheritDoc} */ public TypeVariableDefinition typeVariable(String symbol, Type... bound) { return typeVariable(symbol, Arrays.asList(bound)); } /** * {@inheritDoc} */ public TypeVariableDefinition typeVariable(String symbol, List bounds) { return typeVariable(symbol, new TypeList.Generic.ForLoadedTypes(bounds)); } /** * {@inheritDoc} */ public TypeVariableDefinition typeVariable(String symbol, TypeDefinition... bound) { return typeVariable(symbol, Arrays.asList(bound)); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable defineField(String name, Type type, ModifierContributor.ForField... modifierContributor) { return defineField(name, type, Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable defineField(String name, Type type, Collection modifierContributors) { return defineField(name, type, ModifierContributor.Resolver.of(modifierContributors).resolve()); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable defineField(String name, Type type, int modifiers) { return defineField(name, TypeDefinition.Sort.describe(type), modifiers); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable defineField(String name, TypeDefinition type, ModifierContributor.ForField... modifierContributor) { return defineField(name, type, Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable defineField(String name, TypeDefinition type, Collection modifierContributors) { return defineField(name, type, ModifierContributor.Resolver.of(modifierContributors).resolve()); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable define(Field field) { return define(new FieldDescription.ForLoadedField(field)); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable define(FieldDescription field) { return defineField(field.getName(), field.getType(), field.getModifiers()); } /** * {@inheritDoc} */ public FieldDefinition.Optional serialVersionUid(long serialVersionUid) { return defineField("serialVersionUID", long.class, Visibility.PRIVATE, FieldManifestation.FINAL, Ownership.STATIC).value(serialVersionUid); } /** * {@inheritDoc} */ public FieldDefinition.Valuable field(ElementMatcher matcher) { return field(new LatentMatcher.Resolved(matcher)); } /** * {@inheritDoc} */ public Builder ignoreAlso(ElementMatcher ignoredMethods) { return ignoreAlso(new LatentMatcher.Resolved(ignoredMethods)); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineMethod(String name, Type returnType, ModifierContributor.ForMethod... modifierContributor) { return defineMethod(name, returnType, Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineMethod(String name, Type returnType, Collection modifierContributors) { return defineMethod(name, returnType, ModifierContributor.Resolver.of(modifierContributors).resolve()); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineMethod(String name, Type returnType, int modifiers) { return defineMethod(name, TypeDefinition.Sort.describe(returnType), modifiers); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineMethod(String name, TypeDefinition returnType, ModifierContributor.ForMethod... modifierContributor) { return defineMethod(name, returnType, Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineMethod(String name, TypeDefinition returnType, Collection modifierContributors) { return defineMethod(name, returnType, ModifierContributor.Resolver.of(modifierContributors).resolve()); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineConstructor(ModifierContributor.ForMethod... modifierContributor) { return defineConstructor(Arrays.asList(modifierContributor)); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineConstructor(Collection modifierContributors) { return defineConstructor(ModifierContributor.Resolver.of(modifierContributors).resolve()); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition define(Method method) { return define(new MethodDescription.ForLoadedMethod(method)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition define(Constructor constructor) { return define(new MethodDescription.ForLoadedConstructor(constructor)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition define(MethodDescription methodDescription) { MethodDefinition.ParameterDefinition.Initial initialParameterDefinition = methodDescription.isConstructor() ? defineConstructor(methodDescription.getModifiers()) : defineMethod(methodDescription.getInternalName(), methodDescription.getReturnType(), methodDescription.getModifiers()); ParameterList parameterList = methodDescription.getParameters(); MethodDefinition.ExceptionDefinition exceptionDefinition; if (parameterList.hasExplicitMetaData()) { MethodDefinition.ParameterDefinition 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 typeVariableDefinition = exceptionDefinition.throwing(methodDescription.getExceptionTypes()); for (TypeDescription.Generic typeVariable : methodDescription.getTypeVariables()) { typeVariableDefinition = typeVariableDefinition.typeVariable(typeVariable.getSymbol(), typeVariable.getUpperBounds()); } return typeVariableDefinition; } /** * {@inheritDoc} */ public FieldDefinition.Optional defineProperty(String name, Type type) { return defineProperty(name, TypeDefinition.Sort.describe(type)); } /** * {@inheritDoc} */ public FieldDefinition.Optional defineProperty(String name, Type type, boolean readOnly) { return defineProperty(name, TypeDefinition.Sort.describe(type), readOnly); } /** * {@inheritDoc} */ public FieldDefinition.Optional defineProperty(String name, TypeDefinition type) { return defineProperty(name, type, false); } /** * {@inheritDoc} */ public FieldDefinition.Optional defineProperty(String name, TypeDefinition type, boolean readOnly) { if (name.length() == 0) { 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 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); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition method(ElementMatcher matcher) { return invokable(isMethod().and(matcher)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition constructor(ElementMatcher matcher) { return invokable(isConstructor().and(matcher)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition invokable(ElementMatcher matcher) { return invokable(new LatentMatcher.Resolved(matcher)); } /** * {@inheritDoc} */ public Builder withHashCodeEquals() { return method(isHashCode()) .intercept(HashCodeMethod.usingDefaultOffset().withIgnoredFields(isSynthetic())) .method(isEquals()) .intercept(EqualsMethod.isolated().withIgnoredFields(isSynthetic())); } /** * {@inheritDoc} */ public Builder withToString() { return method(isToString()).intercept(ToStringMethod.prefixedBySimpleClassName()); } /** * {@inheritDoc} */ public Builder require(TypeDescription type, byte[] binaryRepresentation) { return require(type, binaryRepresentation, LoadedTypeInitializer.NoOp.INSTANCE); } /** * {@inheritDoc} */ public Builder require(TypeDescription type, byte[] binaryRepresentation, LoadedTypeInitializer typeInitializer) { return require(new Default(type, binaryRepresentation, typeInitializer, Collections.emptyList())); } /** * {@inheritDoc} */ public Builder require(DynamicType... auxiliaryType) { return require(Arrays.asList(auxiliaryType)); } /** * {@inheritDoc} */ public Unloaded make(TypePool typePool) { return make(TypeResolutionStrategy.Passive.INSTANCE, typePool); } /** * {@inheritDoc} */ public Unloaded make() { return make(TypeResolutionStrategy.Passive.INSTANCE); } /** * A delegator for a dynamic type builder delegating all invocations to another dynamic type builder. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ public abstract static class Delegator extends AbstractBase { /** * {@inheritDoc} */ public Builder visit(AsmVisitorWrapper asmVisitorWrapper) { return materialize().visit(asmVisitorWrapper); } /** * {@inheritDoc} */ public Builder initializer(LoadedTypeInitializer loadedTypeInitializer) { return materialize().initializer(loadedTypeInitializer); } /** * {@inheritDoc} */ public Builder annotateType(Collection annotations) { return materialize().annotateType(annotations); } /** * {@inheritDoc} */ public Builder attribute(TypeAttributeAppender typeAttributeAppender) { return materialize().attribute(typeAttributeAppender); } /** * {@inheritDoc} */ public Builder modifiers(int modifiers) { return materialize().modifiers(modifiers); } /** * {@inheritDoc} */ public Builder merge(Collection modifierContributors) { return materialize().merge(modifierContributors); } /** * {@inheritDoc} */ public Builder name(String name) { return materialize().name(name); } /** * {@inheritDoc} */ public Builder topLevelType() { return materialize().topLevelType(); } /** * {@inheritDoc} */ public InnerTypeDefinition.ForType innerTypeOf(TypeDescription type) { return materialize().innerTypeOf(type); } /** * {@inheritDoc} */ public InnerTypeDefinition innerTypeOf(MethodDescription.InDefinedShape methodDescription) { return materialize().innerTypeOf(methodDescription); } /** * {@inheritDoc} */ public Builder declaredTypes(Collection types) { return materialize().declaredTypes(types); } /** * {@inheritDoc} */ public Builder nestHost(TypeDescription type) { return materialize().nestHost(type); } /** * {@inheritDoc} */ public Builder nestMembers(Collection types) { return materialize().nestMembers(types); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition.Optional implement(Collection interfaceTypes) { return materialize().implement(interfaceTypes); } /** * {@inheritDoc} */ public Builder initializer(ByteCodeAppender byteCodeAppender) { return materialize().initializer(byteCodeAppender); } /** * {@inheritDoc} */ public Builder ignoreAlso(ElementMatcher ignoredMethods) { return materialize().ignoreAlso(ignoredMethods); } /** * {@inheritDoc} */ public Builder ignoreAlso(LatentMatcher ignoredMethods) { return materialize().ignoreAlso(ignoredMethods); } /** * {@inheritDoc} */ public TypeVariableDefinition typeVariable(String symbol, Collection bounds) { return materialize().typeVariable(symbol, bounds); } /** * {@inheritDoc} */ public Builder transform(ElementMatcher matcher, Transformer transformer) { return materialize().transform(matcher, transformer); } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable defineField(String name, TypeDefinition type, int modifiers) { return materialize().defineField(name, type, modifiers); } /** * {@inheritDoc} */ public FieldDefinition.Valuable field(LatentMatcher matcher) { return materialize().field(matcher); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineMethod(String name, TypeDefinition returnType, int modifiers) { return materialize().defineMethod(name, returnType, modifiers); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineConstructor(int modifiers) { return materialize().defineConstructor(modifiers); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition invokable(LatentMatcher matcher) { return materialize().invokable(matcher); } /** * {@inheritDoc} */ public Builder require(Collection auxiliaryTypes) { return materialize().require(auxiliaryTypes); } /** * {@inheritDoc} */ public DynamicType.Unloaded make() { return materialize().make(); } /** * {@inheritDoc} */ public Unloaded make(TypeResolutionStrategy typeResolutionStrategy) { return materialize().make(typeResolutionStrategy); } /** * {@inheritDoc} */ public Unloaded make(TypePool typePool) { return materialize().make(typePool); } /** * {@inheritDoc} */ public Unloaded 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 materialize(); } /** * An adapter implementation of a dynamic type builder. * * @param A loaded type that the built type is guaranteed to be a subclass of. */ @HashCodeAndEqualsPlugin.Enhance public abstract static class Adapter extends AbstractBase { /** * 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 ignoredMethods; /** * A list of explicitly defined auxiliary types. */ protected final List 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 ignoredMethods, List 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; } /** * {@inheritDoc} */ public FieldDefinition.Optional.Valuable defineField(String name, TypeDefinition type, int modifiers) { return new FieldDefinitionAdapter(new FieldDescription.Token(name, modifiers, type.asGenericType())); } /** * {@inheritDoc} */ public FieldDefinition.Valuable field(LatentMatcher matcher) { return new FieldMatchAdapter(matcher); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineMethod(String name, TypeDefinition returnType, int modifiers) { return new MethodDefinitionAdapter(new MethodDescription.Token(name, modifiers, returnType.asGenericType())); } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Initial defineConstructor(int modifiers) { return new MethodDefinitionAdapter(new MethodDescription.Token(modifiers)); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition invokable(LatentMatcher matcher) { return new MethodMatchAdapter(matcher); } /** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition.Optional implement(Collection interfaceTypes) { return new OptionalMethodMatchAdapter(new TypeList.Generic.Explicit(new ArrayList(interfaceTypes))); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") // In absence of @SafeVarargs public Builder ignoreAlso(LatentMatcher ignoredMethods) { return materialize(instrumentedType, fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, new LatentMatcher.Disjunction(this.ignoredMethods, ignoredMethods), auxiliaryTypes); } /** * {@inheritDoc} */ public Builder initializer(ByteCodeAppender byteCodeAppender) { return materialize(instrumentedType.withInitializer(byteCodeAppender), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder initializer(LoadedTypeInitializer loadedTypeInitializer) { return materialize(instrumentedType.withInitializer(loadedTypeInitializer), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder name(String name) { return materialize(instrumentedType.withName(name), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder modifiers(int modifiers) { return materialize(instrumentedType.withModifiers(modifiers), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder merge(Collection 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); } /** * {@inheritDoc} */ public Builder 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); } /** * {@inheritDoc} */ public InnerTypeDefinition.ForType innerTypeOf(TypeDescription type) { return new InnerTypeDefinitionForTypeAdapter(type); } /** * {@inheritDoc} */ public InnerTypeDefinition innerTypeOf(MethodDescription.InDefinedShape methodDescription) { return methodDescription.isTypeInitializer() ? new InnerTypeDefinitionForTypeAdapter(methodDescription.getDeclaringType()) : new InnerTypeDefinitionForMethodAdapter(methodDescription); } /** * {@inheritDoc} */ public Builder declaredTypes(Collection types) { return materialize(instrumentedType.withDeclaredTypes(new TypeList.Explicit(new ArrayList(types))), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder nestHost(TypeDescription type) { return materialize(instrumentedType.withNestHost(type), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder nestMembers(Collection types) { return materialize(instrumentedType.withNestMembers(new TypeList.Explicit(new ArrayList(types))), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public TypeVariableDefinition typeVariable(String symbol, Collection bounds) { return new TypeVariableDefinitionAdapter(new TypeVariableToken(symbol, new TypeList.Generic.Explicit(new ArrayList(bounds)))); } /** * {@inheritDoc} */ public Builder transform(ElementMatcher matcher, Transformer transformer) { return materialize(instrumentedType.withTypeVariables(matcher, transformer), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder 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); } /** * {@inheritDoc} */ public Builder annotateType(Collection annotations) { return materialize(instrumentedType.withAnnotations(new ArrayList(annotations)), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public Builder 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); } /** * {@inheritDoc} */ public Builder require(Collection auxiliaryTypes) { return materialize(instrumentedType, fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, CompoundList.of(this.auxiliaryTypes, new ArrayList(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 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 ignoredMethods, List auxiliaryTypes); /** * An adapter for applying an inner type definition for an outer type. */ @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true) protected class InnerTypeDefinitionForTypeAdapter extends Builder.AbstractBase.Delegator implements InnerTypeDefinition.ForType { /** * 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; } /** * {@inheritDoc} */ public Builder 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); } /** * {@inheritDoc} */ public Builder 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 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 implements InnerTypeDefinition { /** * 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; } /** * {@inheritDoc} */ public Builder 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 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 { /** * 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; } /** * {@inheritDoc} */ public TypeVariableDefinition annotateTypeVariable(Collection annotations) { return new TypeVariableDefinitionAdapter(new TypeVariableToken(token.getSymbol(), token.getBounds(), CompoundList.of(token.getAnnotations(), new ArrayList(annotations)))); } @Override protected Builder 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 { /** * 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.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 transformer, Object defaultValue, FieldDescription.Token token) { super(fieldAttributeAppenderFactory, transformer, defaultValue); this.token = token; } /** * {@inheritDoc} */ public Optional annotateField(Collection annotations) { return new FieldDefinitionAdapter(fieldAttributeAppenderFactory, transformer, defaultValue, new FieldDescription.Token(token.getName(), token.getModifiers(), token.getType(), CompoundList.of(token.getAnnotations(), new ArrayList(annotations)))); } @Override protected Builder 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 materialize(FieldAttributeAppender.Factory fieldAttributeAppenderFactory, Transformer 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 { /** * The matcher for any fields to apply this matcher to. */ private final LatentMatcher matcher; /** * Creates a new field match adapter. * * @param matcher The matcher for any fields to apply this matcher to. */ protected FieldMatchAdapter(LatentMatcher matcher) { this(FieldAttributeAppender.NoOp.INSTANCE, Transformer.NoOp.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 transformer, Object defaultValue, LatentMatcher matcher) { super(fieldAttributeAppenderFactory, transformer, defaultValue); this.matcher = matcher; } /** * {@inheritDoc} */ public Optional annotateField(Collection annotations) { return attribute(new FieldAttributeAppender.Explicit(new ArrayList(annotations))); } @Override protected Builder 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 materialize(FieldAttributeAppender.Factory fieldAttributeAppenderFactory, Transformer 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 { /** * 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; } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Annotatable withParameter(TypeDefinition type, String name, int modifiers) { return new ParameterAnnotationAdapter(new ParameterDescription.Token(type.asGenericType(), name, modifiers)); } /** * {@inheritDoc} */ public Simple.Annotatable withParameter(TypeDefinition type) { return new SimpleParameterAnnotationAdapter(new ParameterDescription.Token(type.asGenericType())); } /** * {@inheritDoc} */ public MethodDefinition.ExceptionDefinition throwing(Collection 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(types))), token.getAnnotations(), token.getDefaultValue(), token.getReceiverType())); } /** * {@inheritDoc} */ public MethodDefinition.TypeVariableDefinition.Annotatable typeVariable(String symbol, Collection bounds) { return new TypeVariableAnnotationAdapter(new TypeVariableToken(symbol, new TypeList.Generic.Explicit(new ArrayList(bounds)))); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition intercept(Implementation implementation) { return materialize(new MethodRegistry.Handler.ForImplementation(implementation)); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition 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); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition 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 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 { /** * 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 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())); } /** * {@inheritDoc} */ public Annotatable annotateTypeVariable(Collection annotations) { return new TypeVariableAnnotationAdapter(new TypeVariableToken(token.getSymbol(), token.getBounds(), CompoundList.of(token.getAnnotations(), new ArrayList(annotations)))); } } /** * An annotation adapter for a parameter definition. */ @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true) protected class ParameterAnnotationAdapter extends MethodDefinition.ParameterDefinition.Annotatable.AbstractBase.Adapter { /** * 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; } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Annotatable annotateParameter(Collection annotations) { return new ParameterAnnotationAdapter(new ParameterDescription.Token(token.getType(), CompoundList.of(token.getAnnotations(), new ArrayList(annotations)), token.getName(), token.getModifiers())); } @Override protected MethodDefinition.ParameterDefinition 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 { /** * 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; } /** * {@inheritDoc} */ public MethodDefinition.ParameterDefinition.Simple.Annotatable annotateParameter(Collection annotations) { return new SimpleParameterAnnotationAdapter(new ParameterDescription.Token(token.getType(), CompoundList.of(token.getAnnotations(), new ArrayList(annotations)), token.getName(), token.getModifiers())); } @Override protected MethodDefinition.ParameterDefinition.Simple 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 { /** * 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.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 transformer) { super(handler, methodAttributeAppenderFactory, transformer); } /** * {@inheritDoc} */ public MethodDefinition 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); } /** * {@inheritDoc} */ public MethodDefinition annotateMethod(Collection 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(annotations)), token.getDefaultValue(), token.getReceiverType())).new AnnotationAdapter(handler, methodAttributeAppenderFactory, transformer); } /** * {@inheritDoc} */ public MethodDefinition annotateParameter(int index, Collection annotations) { List parameterTokens = new ArrayList(token.getParameterTokens()); parameterTokens.set(index, new ParameterDescription.Token(token.getParameterTokens().get(index).getType(), CompoundList.of(token.getParameterTokens().get(index).getAnnotations(), new ArrayList(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 materialize(MethodRegistry.Handler handler, MethodAttributeAppender.Factory methodAttributeAppenderFactory, Transformer transformer) { return new AnnotationAdapter(handler, methodAttributeAppenderFactory, transformer); } @Override protected Builder 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 { /** * The method matcher of this adapter. */ private final LatentMatcher matcher; /** * Creates a new method match adapter. * * @param matcher The method matcher of this adapter. */ protected MethodMatchAdapter(LatentMatcher matcher) { this.matcher = matcher; } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition intercept(Implementation implementation) { return materialize(new MethodRegistry.Handler.ForImplementation(implementation)); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition withoutCode() { return materialize(MethodRegistry.Handler.ForAbstractMethod.INSTANCE); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition 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 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 { /** * 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.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 transformer) { super(handler, methodAttributeAppenderFactory, transformer); } /** * {@inheritDoc} */ public MethodDefinition receiverType(TypeDescription.Generic receiverType) { return new AnnotationAdapter(handler, new MethodAttributeAppender.Factory.Compound(methodAttributeAppenderFactory, new MethodAttributeAppender.ForReceiverType(receiverType)), transformer); } /** * {@inheritDoc} */ public MethodDefinition annotateMethod(Collection annotations) { return new AnnotationAdapter(handler, new MethodAttributeAppender.Factory.Compound(methodAttributeAppenderFactory, new MethodAttributeAppender.Explicit(new ArrayList(annotations))), transformer); } /** * {@inheritDoc} */ public MethodDefinition annotateParameter(int index, Collection annotations) { return new AnnotationAdapter(handler, new MethodAttributeAppender.Factory.Compound(methodAttributeAppenderFactory, new MethodAttributeAppender.Explicit(index, new ArrayList(annotations))), transformer); } @Override protected MethodDefinition materialize(MethodRegistry.Handler handler, MethodAttributeAppender.Factory methodAttributeAppenderFactory, Transformer transformer) { return new AnnotationAdapter(handler, methodAttributeAppenderFactory, transformer); } @Override protected Builder 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 implements MethodDefinition.ImplementationDefinition.Optional { /** * 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 materialize() { return Adapter.this.materialize(instrumentedType.withInterfaces(interfaces), fieldRegistry, methodRegistry, typeAttributeAppender, asmVisitorWrapper, classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, classWriterStrategy, ignoredMethods, auxiliaryTypes); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition intercept(Implementation implementation) { return interfaceType().intercept(implementation); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition withoutCode() { return interfaceType().withoutCode(); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(AnnotationValue annotationValue) { return interfaceType().defaultValue(annotationValue); } /** * {@inheritDoc} */ public MethodDefinition.ReceiverTypeDefinition defaultValue(V value, Class type) { return interfaceType().defaultValue(value, type); } /** * Returns a matcher for the interfaces' methods. * * @return A matcher for the interfaces' methods. */ private MethodDefinition.ImplementationDefinition interfaceType() { ElementMatcher.Junction 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 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 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 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 The least specific type of class loader this strategy can apply to. * @return This dynamic type in its loaded state. * @see org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.loading.ClassLoadingStrategy.Default */ Loaded load(S classLoader, ClassLoadingStrategy 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 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 include(List dynamicTypes); } /** * A dynamic type that has been loaded into the running instance of the Java virtual machine. * * @param 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 extends DynamicType { /** * Returns the loaded main class. * * @return A loaded class representation of this dynamic type. */ Class getLoaded(); /** *

* Returns a map of all loaded auxiliary types to this dynamic type. *

*

* Note: 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. *

* * @return A mapping from the fully qualified names of all auxiliary types to their loaded class representations. */ Map> 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 dispacher for applying a file copy. */ protected static final Dispatcher DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE); /** * 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 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 auxiliaryTypes) { this.typeDescription = typeDescription; this.binaryRepresentation = binaryRepresentation; this.loadedTypeInitializer = loadedTypeInitializer; this.auxiliaryTypes = auxiliaryTypes; } /** * {@inheritDoc} */ public TypeDescription getTypeDescription() { return typeDescription; } /** * {@inheritDoc} */ public Map getAllTypes() { Map allTypes = new LinkedHashMap(); allTypes.put(typeDescription, binaryRepresentation); for (DynamicType auxiliaryType : auxiliaryTypes) { allTypes.putAll(auxiliaryType.getAllTypes()); } return allTypes; } /** * {@inheritDoc} */ public Map getLoadedTypeInitializers() { Map classLoadingCallbacks = new HashMap(); for (DynamicType auxiliaryType : auxiliaryTypes) { classLoadingCallbacks.putAll(auxiliaryType.getLoadedTypeInitializers()); } classLoadingCallbacks.put(typeDescription, loadedTypeInitializer); return classLoadingCallbacks; } /** * {@inheritDoc} */ public boolean hasAliveLoadedTypeInitializers() { for (LoadedTypeInitializer loadedTypeInitializer : getLoadedTypeInitializers().values()) { if (loadedTypeInitializer.isAlive()) { return true; } } return false; } /** * {@inheritDoc} */ @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "The array is not to be modified by contract") public byte[] getBytes() { return binaryRepresentation; } /** * {@inheritDoc} */ public Map getAuxiliaryTypes() { Map auxiliaryTypes = new HashMap(); for (DynamicType auxiliaryType : this.auxiliaryTypes) { auxiliaryTypes.put(auxiliaryType.getTypeDescription(), auxiliaryType.getBytes()); auxiliaryTypes.putAll(auxiliaryType.getAuxiliaryTypes()); } return auxiliaryTypes; } /** * {@inheritDoc} */ public Map saveIn(File folder) throws IOException { Map files = new HashMap(); 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(); } files.put(typeDescription, target); for (DynamicType auxiliaryType : auxiliaryTypes) { files.putAll(auxiliaryType.saveIn(folder)); } return files; } /** * {@inheritDoc} */ public File inject(File sourceJar, File targetJar) throws IOException { return sourceJar.equals(targetJar) ? inject(sourceJar) : doInject(sourceJar, targetJar); } /** * {@inheritDoc} */ public File inject(File jar) throws IOException { File temporary = doInject(jar, File.createTempFile(jar.getName(), TEMP_SUFFIX)); boolean delete = true; try { delete = DISPATCHER.copy(temporary, jar); } finally { if (delete && !temporary.delete()) { temporary.deleteOnExit(); } } return jar; } /** * Injects this dynamic type into a source jar and writes the result to the target jar. * * @param sourceJar The source jar. * @param targetJar The target jar. * @return The jar file that was written to. * @throws IOException If an I/O error occurs. */ private File doInject(File sourceJar, File targetJar) throws IOException { JarInputStream inputStream = new JarInputStream(new FileInputStream(sourceJar)); try { if (!targetJar.isFile() && !targetJar.createNewFile()) { throw new IllegalArgumentException("Could not create file: " + targetJar); } Manifest manifest = inputStream.getManifest(); JarOutputStream outputStream = manifest == null ? new JarOutputStream(new FileOutputStream(targetJar)) : new JarOutputStream(new FileOutputStream(targetJar), manifest); try { Map rawAuxiliaryTypes = getAuxiliaryTypes(); Map files = new HashMap(); for (Map.Entry 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 = inputStream.getNextJarEntry()) != null) { byte[] replacement = files.remove(jarEntry.getName()); if (replacement == null) { outputStream.putNextEntry(jarEntry); byte[] buffer = new byte[BUFFER_SIZE]; int index; while ((index = inputStream.read(buffer)) != END_OF_FILE) { outputStream.write(buffer, FROM_BEGINNING, index); } } else { outputStream.putNextEntry(new JarEntry(jarEntry.getName())); outputStream.write(replacement); } inputStream.closeEntry(); outputStream.closeEntry(); } for (Map.Entry entry : files.entrySet()) { outputStream.putNextEntry(new JarEntry(entry.getKey())); outputStream.write(entry.getValue()); outputStream.closeEntry(); } } finally { outputStream.close(); } } finally { inputStream.close(); } return targetJar; } /** * {@inheritDoc} */ public File toJar(File file) throws IOException { Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, MANIFEST_VERSION); return toJar(file, manifest); } /** * {@inheritDoc} */ 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 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 dispatcher that allows for file copy operations based on NIO2 if available. */ protected interface Dispatcher { /** * Copies the source file to the target location. * * @param source The source file. * @param target The target file. * @return {@code true} if the source file needs to be deleted. * @throws IOException If an I/O error occurs. */ boolean copy(File source, File target) throws IOException; /** * An action for creating a dispatcher. */ enum CreationAction implements PrivilegedAction { /** * The singleton instance. */ INSTANCE; /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public Dispatcher run() { try { Class path = Class.forName("java.nio.file.Path"); Object[] arguments = (Object[]) Array.newInstance(Class.forName("java.nio.file.CopyOption"), 1); arguments[0] = Enum.valueOf((Class) Class.forName("java.nio.file.StandardCopyOption"), "REPLACE_EXISTING"); return new ForJava7CapableVm(File.class.getMethod("toPath"), Class.forName("java.nio.file.Files").getMethod("move", path, path, arguments.getClass()), arguments); } catch (Throwable ignored) { return ForLegacyVm.INSTANCE; } } } /** * A legacy dispatcher that is not capable of NIO. */ enum ForLegacyVm implements Dispatcher { /** * The singleton instance. */ INSTANCE; /** * {@inheritDoc} */ public boolean copy(File source, File target) throws IOException { InputStream inputStream = new FileInputStream(source); try { OutputStream outputStream = new FileOutputStream(target); try { byte[] buffer = new byte[BUFFER_SIZE]; int index; while ((index = inputStream.read(buffer)) != END_OF_FILE) { outputStream.write(buffer, FROM_BEGINNING, index); } } finally { outputStream.close(); } } finally { inputStream.close(); } return true; } } /** * A dispatcher for VMs that are capable of NIO2. */ @HashCodeAndEqualsPlugin.Enhance class ForJava7CapableVm implements Dispatcher { /** * The {@code java.io.File#toPath()} method. */ private final Method toPath; /** * The {@code java.nio.Files#copy(Path,Path,CopyOption[])} method. */ private final Method move; /** * The copy options to apply. */ private final Object[] copyOptions; /** * Creates a new NIO2 capable dispatcher. * * @param toPath The {@code java.io.File#toPath()} method. * @param move The {@code java.nio.Files#move(Path,Path,CopyOption[])} method. * @param copyOptions The copy options to apply. */ protected ForJava7CapableVm(Method toPath, Method move, Object[] copyOptions) { this.toPath = toPath; this.move = move; this.copyOptions = copyOptions; } /** * {@inheritDoc} */ public boolean copy(File source, File target) throws IOException { try { move.invoke(null, toPath.invoke(source), toPath.invoke(target), copyOptions); return false; } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access NIO file copy", exception); } catch (InvocationTargetException exception) { Throwable cause = exception.getCause(); if (cause instanceof IOException) { throw (IOException) cause; } else { throw new IllegalStateException("Cannot execute NIO file copy", cause); } } } } } /** * A default implementation of an unloaded dynamic type. * * @param 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 extends Default implements DynamicType.Unloaded { /** * 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 auxiliaryTypes, TypeResolutionStrategy.Resolved typeResolutionStrategy) { super(typeDescription, binaryRepresentation, loadedTypeInitializer, auxiliaryTypes); this.typeResolutionStrategy = typeResolutionStrategy; } /** * {@inheritDoc} */ public DynamicType.Loaded load(ClassLoader classLoader) { return classLoader instanceof InjectionClassLoader && !((InjectionClassLoader) classLoader).isSealed() ? load((InjectionClassLoader) classLoader, InjectionClassLoader.Strategy.INSTANCE) : load(classLoader, ClassLoadingStrategy.Default.WRAPPER); } /** * {@inheritDoc} */ public DynamicType.Loaded load(S classLoader, ClassLoadingStrategy classLoadingStrategy) { return new Default.Loaded(typeDescription, binaryRepresentation, loadedTypeInitializer, auxiliaryTypes, typeResolutionStrategy.initialize(this, classLoader, classLoadingStrategy)); } /** * {@inheritDoc} */ public DynamicType.Unloaded include(DynamicType... dynamicType) { return include(Arrays.asList(dynamicType)); } /** * {@inheritDoc} */ public DynamicType.Unloaded include(List dynamicType) { return new Default.Unloaded(typeDescription, binaryRepresentation, loadedTypeInitializer, CompoundList.of(auxiliaryTypes, dynamicType), typeResolutionStrategy); } } /** * A default implementation of a loaded dynamic type. * * @param 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 extends Default implements DynamicType.Loaded { /** * The loaded types for the given loaded dynamic type. */ private final Map> 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 auxiliaryTypes, Map> loadedTypes) { super(typeDescription, typeByte, loadedTypeInitializer, auxiliaryTypes); this.loadedTypes = loadedTypes; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public Class getLoaded() { return (Class) loadedTypes.get(typeDescription); } /** * {@inheritDoc} */ public Map> getLoadedAuxiliaryTypes() { Map> loadedAuxiliaryTypes = new HashMap>( loadedTypes); loadedAuxiliaryTypes.remove(typeDescription); return loadedAuxiliaryTypes; } } } }