// Generated by delombok at Sun Feb 26 12:31:38 KST 2017
package scouter.bytebuddy;
import scouter.bytebuddy.agent.builder.AgentBuilder;
import scouter.bytebuddy.description.field.FieldDescription;
import scouter.bytebuddy.description.method.MethodDescription;
import scouter.bytebuddy.description.modifier.*;
import scouter.bytebuddy.description.type.PackageDescription;
import scouter.bytebuddy.description.type.TypeDefinition;
import scouter.bytebuddy.description.type.TypeDescription;
import scouter.bytebuddy.description.type.TypeList;
import scouter.bytebuddy.dynamic.ClassFileLocator;
import scouter.bytebuddy.dynamic.DynamicType;
import scouter.bytebuddy.dynamic.TargetType;
import scouter.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import scouter.bytebuddy.dynamic.scaffold.InstrumentedType;
import scouter.bytebuddy.dynamic.scaffold.MethodGraph;
import scouter.bytebuddy.dynamic.scaffold.TypeValidation;
import scouter.bytebuddy.dynamic.scaffold.inline.MethodNameTransformer;
import scouter.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder;
import scouter.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder;
import scouter.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import scouter.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder;
import scouter.bytebuddy.implementation.Implementation;
import scouter.bytebuddy.implementation.MethodCall;
import scouter.bytebuddy.implementation.SuperMethodCall;
import scouter.bytebuddy.implementation.attribute.AnnotationRetention;
import scouter.bytebuddy.implementation.attribute.AnnotationValueFilter;
import scouter.bytebuddy.implementation.auxiliary.AuxiliaryType;
import scouter.bytebuddy.implementation.bytecode.ByteCodeAppender;
import scouter.bytebuddy.implementation.bytecode.Duplication;
import scouter.bytebuddy.implementation.bytecode.StackManipulation;
import scouter.bytebuddy.implementation.bytecode.TypeCreation;
import scouter.bytebuddy.implementation.bytecode.assign.Assigner;
import scouter.bytebuddy.implementation.bytecode.assign.TypeCasting;
import scouter.bytebuddy.implementation.bytecode.collection.ArrayFactory;
import scouter.bytebuddy.implementation.bytecode.constant.IntegerConstant;
import scouter.bytebuddy.implementation.bytecode.constant.TextConstant;
import scouter.bytebuddy.implementation.bytecode.member.FieldAccess;
import scouter.bytebuddy.implementation.bytecode.member.MethodInvocation;
import scouter.bytebuddy.implementation.bytecode.member.MethodReturn;
import scouter.bytebuddy.matcher.ElementMatcher;
import scouter.bytebuddy.matcher.LatentMatcher;
import scouter.bytebuddy.jar.asm.MethodVisitor;
import scouter.bytebuddy.jar.asm.Opcodes;
import scouter.bytebuddy.matcher.ElementMatchers;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.*;
/**
* Instances of this class serve as a focus point for configuration of the library's behavior and as an entry point
* to any form of code generation using the library. For this purpose, Byte Buddy offers a fluent API which allows
* for the step-wise generation of a new Java type. A type is generated either by:
* <ul>
* <li><b>Subclassing</b> some type: A subclass - as the name suggests - extends another, existing Java type. Virtual
* members of the generated type's super types can be overridden. Subclasses can also be interface extensions of one
* or several interfaces.</li>
* <li><b>Redefining</b> a type: By redefining a type, it is not only possible to override virtual methods of the
* redefined type but also to redefine existing methods. This way, it is also possible to change the behavior of
* non-virtual methods and constructors of the redefined type.</li>
* <li><b>Rebasing</b> a type: Rebasing a type works similar to creating a subclass, i.e. any method being overridden
* is still capable of invoking any original code of the rebased type. Any rebased method is however inlined into the
* rebased type and any original code is preserved automatically. This way, the type's identity does not change.</li>
* </ul>
* Byte Buddy's API does not change when a type is rebased, redefined or subclassed. All types are created via the
* {@link DynamicType.Builder} interface. Byte Buddy's API is expressed by fully immutable
* components and is therefore thread-safe. As a consequence, method calls must be chained for all of Byte Buddy's
* component, e.g. a method call like the following has no effect:
* <pre>
* ByteBuddy byteBuddy = new ByteBuddy();
* byteBuddy.foo()</pre>
* Instead, the following method chain is corrent use of the API:
* <pre>
* ByteBuddy byteBuddy = new ByteBuddy().foo();</pre>
* <p>
* For the creation of Java agents, Byte Buddy offers a convenience API implemented by the
* {@link AgentBuilder}. The API wraps a {@link ByteBuddy} instance and offers agent-specific
* configuration opportunities by integrating against the {@link java.lang.instrument.Instrumentation} API.
* </p>
*
* @see AgentBuilder
*/
public class ByteBuddy {
private static final String BYTE_BUDDY_VERSION = "1.6.9";
/**
* The default prefix for the default {@link NamingStrategy}.
*/
private static final String BYTE_BUDDY_DEFAULT_PREFIX = "ByteBuddy";
/**
* The default suffix when defining a {@link AuxiliaryType.NamingStrategy}.
*/
private static final String BYTE_BUDDY_DEFAULT_SUFFIX = "auxiliary";
/**
* The class file version to use for types that are not based on an existing class file.
*/
protected final ClassFileVersion classFileVersion;
/**
* The naming strategy to use.
*/
protected final NamingStrategy namingStrategy;
/**
* The naming strategy to use for naming auxiliary types.
*/
protected final AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy;
/**
* The annotation value filter factory to use.
*/
protected final AnnotationValueFilter.Factory annotationValueFilterFactory;
/**
* The annotation retention strategy to use.
*/
protected final AnnotationRetention annotationRetention;
/**
* The implementation context factory to use.
*/
protected final Implementation.Context.Factory implementationContextFactory;
/**
* The method graph compiler to use.
*/
protected final MethodGraph.Compiler methodGraphCompiler;
/**
* The instrumented type factory to use.
*/
protected final InstrumentedType.Factory instrumentedTypeFactory;
/**
* A matcher for identifying methods that should be excluded from instrumentation.
*/
protected final LatentMatcher<? super MethodDescription> ignoredMethods;
/**
* Determines if a type should be explicitly validated.
*/
protected final TypeValidation typeValidation;
/**
* <p>
* Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
* </p>
* <p>
* When creating this configuration, Byte Buddy attempts to discover the current JVM's version. If this
* is not possible, class files are created Java 6-compatible.
* </p>
*
* @see ClassFileVersion#ofThisVm(ClassFileVersion)
*/
public ByteBuddy() {
this(ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V6));
}
/**
* Creates a new Byte Buddy instance with a default configuration that is suitable for most use cases.
*
* @param classFileVersion The class file version to use for types that are not based on an existing class file.
*/
public ByteBuddy(ClassFileVersion classFileVersion) {
this(classFileVersion, new NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_PREFIX), new AuxiliaryType.NamingStrategy.SuffixingRandom(BYTE_BUDDY_DEFAULT_SUFFIX), AnnotationValueFilter.Default.APPEND_DEFAULTS, AnnotationRetention.ENABLED, Implementation.Context.Default.Factory.INSTANCE, MethodGraph.Compiler.DEFAULT, InstrumentedType.Factory.Default.MODIFIABLE, TypeValidation.ENABLED, new LatentMatcher.Resolved<MethodDescription>(ElementMatchers.isSynthetic().or(ElementMatchers.isDefaultFinalizer())));
}
/**
* Creates a new Byte Buddy instance.
*
* @param classFileVersion The class file version to use for types that are not based on an existing class file.
* @param namingStrategy The naming strategy to use.
* @param auxiliaryTypeNamingStrategy The naming strategy to use for naming auxiliary types.
* @param annotationValueFilterFactory The annotation value filter factory to use.
* @param annotationRetention The annotation retention strategy to use.
* @param implementationContextFactory The implementation context factory to use.
* @param methodGraphCompiler The method graph compiler to use.
* @param instrumentedTypeFactory The instrumented type factory to use.
* @param typeValidation Determines if a type should be explicitly validated.
* @param ignoredMethods A matcher for identifying methods that should be excluded from instrumentation.
*/
protected ByteBuddy(ClassFileVersion classFileVersion, NamingStrategy namingStrategy, AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy, AnnotationValueFilter.Factory annotationValueFilterFactory, AnnotationRetention annotationRetention, Implementation.Context.Factory implementationContextFactory, MethodGraph.Compiler methodGraphCompiler, InstrumentedType.Factory instrumentedTypeFactory, TypeValidation typeValidation, LatentMatcher<? super MethodDescription> ignoredMethods) {
this.classFileVersion = classFileVersion;
this.namingStrategy = namingStrategy;
this.auxiliaryTypeNamingStrategy = auxiliaryTypeNamingStrategy;
this.annotationValueFilterFactory = annotationValueFilterFactory;
this.annotationRetention = annotationRetention;
this.implementationContextFactory = implementationContextFactory;
this.methodGraphCompiler = methodGraphCompiler;
this.instrumentedTypeFactory = instrumentedTypeFactory;
this.ignoredMethods = ignoredMethods;
this.typeValidation = typeValidation;
}
/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
* to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
* {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Class, ConstructorStrategy)}.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend.
* @param <T> A loaded type that the generated class is guaranteed to inherit.
* @return A type builder for creating a new class extending the provided class or interface.
*/
@SuppressWarnings("unchecked")
public <T> DynamicType.Builder<T> subclass(Class<T> superType) {
return (DynamicType.Builder<T>) subclass(new TypeDescription.ForLoadedType(superType));
}
/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend.
* @param constructorStrategy A constructor strategy that determines the
* @param <T> A loaded type that the generated class is guaranteed to inherit.
* @return A type builder for creating a new class extending the provided class or interface.
*/
@SuppressWarnings("unchecked")
public <T> DynamicType.Builder<T> subclass(Class<T> superType, ConstructorStrategy constructorStrategy) {
return (DynamicType.Builder<T>) subclass(new TypeDescription.ForLoadedType(superType), constructorStrategy);
}
/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type. Any constructor is implemented
* to only invoke its super type constructor of equal signature. Another behavior can be specified by supplying an explicit
* {@link ConstructorStrategy} by {@link ByteBuddy#subclass(Type, ConstructorStrategy)}.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
* variables that are referenced by the generic type must be declared by the generated subclass before creating
* the type.
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder<?> subclass(Type superType) {
return subclass(TypeDefinition.Sort.describe(superType));
}
/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized
* type. All type variables that are referenced by the generic type must be declared by the
* generated subclass before creating the type.
* @param constructorStrategy A constructor strategy that determines the
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder<?> subclass(Type superType, ConstructorStrategy constructorStrategy) {
return subclass(TypeDefinition.Sort.describe(superType), constructorStrategy);
}
/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type and sets them to be {@code public}.
* Any constructor is implemented to only invoke its super type constructor of equal signature. Another behavior can be specified by
* supplying an explicit {@link ConstructorStrategy} by {@link ByteBuddy#subclass(TypeDefinition, ConstructorStrategy)}.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
* as raw types if they declare type variables.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
* variables that are referenced by the generic type must be declared by the generated subclass before creating
* the type.
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder<?> subclass(TypeDefinition superType) {
return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING);
}
/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
* as raw types if they declare type variables.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized
* type. All type variables that are referenced by the generic type must be declared by the
* generated subclass before creating the type.
* @param constructorStrategy A constructor strategy that determines the
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder<?> subclass(TypeDefinition superType, ConstructorStrategy constructorStrategy) {
TypeDescription.Generic actualSuperType;
TypeList.Generic interfaceTypes;
if (superType.isPrimitive() || superType.isArray() || superType.isFinal()) {
throw new IllegalArgumentException("Cannot subclass primitive, array or final types: " + superType);
} else if (superType.isInterface()) {
actualSuperType = TypeDescription.Generic.OBJECT;
interfaceTypes = new TypeList.Generic.Explicit(superType);
} else {
actualSuperType = superType.asGenericType();
interfaceTypes = new TypeList.Generic.Empty();
}
return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(namingStrategy.subclass(superType.asGenericType()), ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.PLAIN).resolve(superType.getModifiers()), actualSuperType).withInterfaces(interfaceTypes), classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, ignoredMethods, constructorStrategy);
}
/**
* <p>
* Creates a new, plain interface type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @return A type builder that creates a new interface type.
*/
public DynamicType.Builder<?> makeInterface() {
return makeInterface(Collections.<TypeDescription>emptyList());
}
/**
* <p>
* Creates a new interface type that extends the provided interface.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types in a generified state if they declare type variables or an owner type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param interfaceType An interface type that the generated interface implements.
* @param <T> A loaded type that the generated interface is guaranteed to inherit.
* @return A type builder that creates a new interface type.
*/
@SuppressWarnings("unchecked")
public <T> DynamicType.Builder<T> makeInterface(Class<T> interfaceType) {
return (DynamicType.Builder<T>) makeInterface(Collections.<Type>singletonList(interfaceType));
}
/**
* <p>
* Creates a new interface type that extends the provided interface.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables or an owner type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param interfaceType The interface types to implement. The types must be raw or parameterized types. All type
* variables that are referenced by a parameterized type must be declared by the generated
* subclass before creating the type.
* @return A type builder that creates a new interface type.
*/
public DynamicType.Builder<?> makeInterface(Type... interfaceType) {
return makeInterface(Arrays.asList(interfaceType));
}
/**
* <p>
* Creates a new interface type that extends the provided interface.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link Class} values are implemented
* as raw types if they declare type variables or an owner type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param interfaceTypes The interface types to implement. The types must be raw or parameterized types. All
* type variables that are referenced by a parameterized type must be declared by the
* generated subclass before creating the type.
* @return A type builder that creates a new interface type.
*/
public DynamicType.Builder<?> makeInterface(List<? extends Type> interfaceTypes) {
return makeInterface(new TypeList.Generic.ForLoadedTypes(interfaceTypes));
}
/**
* <p>
* Creates a new interface type that extends the provided interface.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
* as raw types if they declare type variables or an owner type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param interfaceType The interface types to implement. The types must be raw or parameterized types. All
* type variables that are referenced by a parameterized type must be declared by the
* generated subclass before creating the type.
* @return A type builder that creates a new interface type.
*/
public DynamicType.Builder<?> makeInterface(TypeDefinition... interfaceType) {
return makeInterface(Arrays.asList(interfaceType));
}
/**
* <p>
* Creates a new interface type that extends the provided interface.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
* as raw types if they declare type variables or an owner type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param interfaceTypes The interface types to implement. The types must be raw or parameterized types. All
* type variables that are referenced by a parameterized type must be declared by the
* generated subclass before creating the type.
* @return A type builder that creates a new interface type.
*/
public DynamicType.Builder<?> makeInterface(Collection<? extends TypeDefinition> interfaceTypes) {
return subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS).implement(interfaceTypes).modifiers(TypeManifestation.INTERFACE, Visibility.PUBLIC);
}
/**
* <p>
* Creates a new package definition. Package definitions are defined by classes named {@code package-info}
* without any methods or fields but permit annotations. Any field or method definition will cause an
* {@link IllegalStateException} to be thrown when the type is created.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param name The fully qualified name of the package.
* @return A type builder that creates a {@code package-info} class file.
*/
public DynamicType.Builder<?> makePackage(String name) {
return new SubclassDynamicTypeBuilder<Object>(instrumentedTypeFactory.subclass(name + "." + PackageDescription.PACKAGE_CLASS_NAME, PackageDescription.PACKAGE_MODIFIERS, TypeDescription.Generic.OBJECT), classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, ignoredMethods, ConstructorStrategy.Default.NO_CONSTRUCTORS);
}
/**
* <p>
* Creates a new {@link Annotation} type. Annotation properties are implemented as non-static, public methods with the
* property type being defined as the return type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @return A type builder that creates a new {@link Annotation} type.
*/
public DynamicType.Builder<? extends Annotation> makeAnnotation() {
return new SubclassDynamicTypeBuilder<Annotation>(instrumentedTypeFactory.subclass(namingStrategy.subclass(TypeDescription.Generic.ANNOTATION), ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.ANNOTATION).resolve(), TypeDescription.Generic.OBJECT).withInterfaces(new TypeList.Generic.Explicit(TypeDescription.Generic.ANNOTATION)), classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, ignoredMethods, ConstructorStrategy.Default.NO_CONSTRUCTORS);
}
/**
* <p>
* Creates a new {@link Enum} type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param value The names of the type's enumeration constants
* @return A type builder for creating an enumeration type.
*/
public DynamicType.Builder<? extends Enum<?>> makeEnumeration(String... value) {
return makeEnumeration(Arrays.asList(value));
}
/**
* <p>
* Creates a new {@link Enum} type.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param values The names of the type's enumeration constants
* @return A type builder for creating an enumeration type.
*/
public DynamicType.Builder<? extends Enum<?>> makeEnumeration(Collection<? extends String> values) {
if (values.isEmpty()) {
throw new IllegalArgumentException("Require at least one enumeration constant");
}
TypeDescription.Generic enumType = TypeDescription.Generic.Builder.parameterizedType(Enum.class, TargetType.class).build();
return new SubclassDynamicTypeBuilder<Enum<?>>(instrumentedTypeFactory.subclass(namingStrategy.subclass(enumType), ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.FINAL, EnumerationState.ENUMERATION).resolve(), enumType), classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, ignoredMethods, ConstructorStrategy.Default.NO_CONSTRUCTORS).defineConstructor(Visibility.PRIVATE).withParameters(String.class, int.class).intercept(SuperMethodCall.INSTANCE).defineMethod(EnumerationImplementation.ENUM_VALUE_OF_METHOD_NAME, TargetType.class, Visibility.PUBLIC, Ownership.STATIC).withParameters(String.class).intercept(MethodCall.invoke(enumType.getDeclaredMethods().filter(ElementMatchers.named(EnumerationImplementation.ENUM_VALUE_OF_METHOD_NAME).and(ElementMatchers.takesArguments(Class.class, String.class))).getOnly()).withOwnType().withArgument(0).withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC)).defineMethod(EnumerationImplementation.ENUM_VALUES_METHOD_NAME, TargetType[].class, Visibility.PUBLIC, Ownership.STATIC).intercept(new EnumerationImplementation(new ArrayList<String>(values)));
}
/**
* <p>
* Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
* by the new implementation.
* </p>
* <p>
* The class file of the redefined type is located by querying the redefined type's class loader by name. For specifying an
* alternative {@link ClassFileLocator}, use {@link ByteBuddy#redefine(Class, ClassFileLocator)}.
* </p>
* <p>
* <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link ClassReloadingStrategy},
* it is important that no fields or methods are added to the redefined class. Note that some {@link Implementation}s implicitly add fields or methods.
* Finally, Byte Buddy might be forced to add a method if a redefined class already defines a class initializer. This can be disabled by setting
* {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link Implementation.Context.Disabled.Factory}
* where the class initializer is retained <i>as is</i>.
* </p>
*
* @param type The type that is being redefined.
* @param <T> The loaded type of the redefined type.
* @return A type builder for redefining the provided type.
*/
public <T> DynamicType.Builder<T> redefine(Class<T> type) {
return redefine(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
}
/**
* <p>
* Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
* by the new implementation.
* </p>
* <p>
* <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link ClassReloadingStrategy},
* it is important that no fields or methods are added to the redefined class. Note that some {@link Implementation}s implicitly add fields or methods.
* Finally, Byte Buddy might be forced to add a method if a redefined class already defines a class initializer. This can be disabled by setting
* {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link Implementation.Context.Disabled.Factory}
* where the class initializer is retained <i>as is</i>.
* </p>
*
* @param type The type that is being redefined.
* @param classFileLocator The class file locator that is queried for the redefined type's class file.
* @param <T> The loaded type of the redefined type.
* @return A type builder for redefining the provided type.
*/
public <T> DynamicType.Builder<T> redefine(Class<T> type, ClassFileLocator classFileLocator) {
return redefine(new TypeDescription.ForLoadedType(type), classFileLocator);
}
/**
* <p>
* Redefines the given type where any intercepted method that is declared by the redefined type is fully replaced
* by the new implementation.
* </p>
* <p>
* <b>Note</b>: When a user redefines a class with the purpose of reloading this class using a {@link ClassReloadingStrategy},
* it is important that no fields or methods are added to the redefined class. Note that some {@link Implementation}s implicitly add fields or methods.
* Finally, Byte Buddy might be forced to add a method if a redefined class already defines a class initializer. This can be disabled by setting
* {@link ByteBuddy#with(Implementation.Context.Factory)} to use a {@link Implementation.Context.Disabled.Factory}
* where the class initializer is retained <i>as is</i>.
* </p>
*
* @param type The type that is being redefined.
* @param classFileLocator The class file locator that is queried for the redefined type's class file.
* @param <T> The loaded type of the redefined type.
* @return A type builder for redefining the provided type.
*/
public <T> DynamicType.Builder<T> redefine(TypeDescription type, ClassFileLocator classFileLocator) {
return new RedefinitionDynamicTypeBuilder<T>(instrumentedTypeFactory.represent(type), classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, ignoredMethods, type, classFileLocator);
}
/**
* <p>
* Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
* rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
* type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
* </p>
* <p>
* The class file of the rebased type is located by querying the rebased type's class loader by name. For specifying an
* alternative {@link ClassFileLocator}, use {@link ByteBuddy#redefine(Class, ClassFileLocator)}.
* </p>
*
* @param type The type that is being rebased.
* @param <T> The loaded type of the rebased type.
* @return A type builder for rebasing the provided type.
*/
public <T> DynamicType.Builder<T> rebase(Class<T> type) {
return rebase(type, ClassFileLocator.ForClassLoader.of(type.getClassLoader()));
}
/**
* <p>
* Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
* rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
* type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
* </p>
* <p>
* When a method is rebased, the original method is copied into a new method with a different name. These names are
* generated automatically by Byte Buddy unless a {@link MethodNameTransformer} is specified explicitly.
* Use {@link ByteBuddy#rebase(Class, ClassFileLocator, MethodNameTransformer)} for doing so.
* </p>
*
* @param type The type that is being rebased.
* @param classFileLocator The class file locator that is queried for the rebased type's class file.
* @param <T> The loaded type of the rebased type.
* @return A type builder for rebasing the provided type.
*/
public <T> DynamicType.Builder<T> rebase(Class<T> type, ClassFileLocator classFileLocator) {
return rebase(new TypeDescription.ForLoadedType(type), classFileLocator);
}
/**
* Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
* rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
* type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
*
* @param type The type that is being rebased.
* @param classFileLocator The class file locator that is queried for the rebased type's class file.
* @param methodNameTransformer The method name transformer for renaming a method that is rebased.
* @param <T> The loaded type of the rebased type.
* @return A type builder for rebasing the provided type.
*/
public <T> DynamicType.Builder<T> rebase(Class<T> type, ClassFileLocator classFileLocator, MethodNameTransformer methodNameTransformer) {
return rebase(new TypeDescription.ForLoadedType(type), classFileLocator, methodNameTransformer);
}
/**
* <p>
* Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
* rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
* type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
* </p>
* <p>
* When a method is rebased, the original method is copied into a new method with a different name. These names are
* generated automatically by Byte Buddy unless a {@link MethodNameTransformer} is specified explicitly.
* Use {@link ByteBuddy#rebase(TypeDescription, ClassFileLocator, MethodNameTransformer)} for doing so.
* </p>
*
* @param type The type that is being rebased.
* @param classFileLocator The class file locator that is queried for the rebased type's class file.
* @param <T> The loaded type of the rebased type.
* @return A type builder for rebasing the provided type.
*/
public <T> DynamicType.Builder<T> rebase(TypeDescription type, ClassFileLocator classFileLocator) {
return rebase(type, classFileLocator, MethodNameTransformer.Suffixing.withRandomSuffix());
}
/**
* Rebases the given type where any intercepted method that is declared by the redefined type is preserved within the
* rebased type's class such that the class's original can be invoked from the new method implementations. Rebasing a
* type can be seen similarly to creating a subclass where the subclass is later merged with the original class file.
*
* @param type The type that is being rebased.
* @param classFileLocator The class file locator that is queried for the rebased type's class file.
* @param methodNameTransformer The method name transformer for renaming a method that is rebased.
* @param <T> The loaded type of the rebased type.
* @return A type builder for rebasing the provided type.
*/
public <T> DynamicType.Builder<T> rebase(TypeDescription type, ClassFileLocator classFileLocator, MethodNameTransformer methodNameTransformer) {
return new RebaseDynamicTypeBuilder<T>(instrumentedTypeFactory.represent(type), classFileVersion, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, typeValidation, ignoredMethods, type, classFileLocator, methodNameTransformer);
}
/**
* Rebases a package. This offers an opportunity to add annotations to the package definition. Packages are defined
* by classes named {@code package-info} without any methods or fields but permit annotations. Any field or method
* definition will cause an {@link IllegalStateException} to be thrown when the type is created.
*
* @param aPackage The package that is being rebased.
* @param classFileLocator The class file locator to use for locating the package's class file.
* @return A type builder for rebasing the given package.
*/
public DynamicType.Builder<?> rebase(Package aPackage, ClassFileLocator classFileLocator) {
return rebase(new PackageDescription.ForLoadedPackage(aPackage), classFileLocator);
}
/**
* Rebases a package. This offers an opportunity to add annotations to the package definition. Packages are defined
* by classes named {@code package-info} without any methods or fields but permit annotations. Any field or method
* definition will cause an {@link IllegalStateException} to be thrown when the type is created.
*
* @param aPackage The package that is being rebased.
* @param classFileLocator The class file locator to use for locating the package's class file.
* @return A type builder for rebasing the given package.
*/
public DynamicType.Builder<?> rebase(PackageDescription aPackage, ClassFileLocator classFileLocator) {
return rebase(new TypeDescription.ForPackageDescription(aPackage), classFileLocator);
}
/**
* Creates a new configuration where all class files that are not based on an existing class file are created
* using the supplied class file version. When creating a Byte Buddy instance by {@link ByteBuddy#ByteBuddy()}, the class
* file version is detected automatically. If the class file version is known before creating a Byte Buddy instance, the
* {@link ByteBuddy#ByteBuddy(ClassFileVersion)} constructor should be used.
*
* @param classFileVersion The class file version to use for types that are not based on an existing class file.
* @return A new Byte Buddy instance that uses the supplied class file version.
*/
public ByteBuddy with(ClassFileVersion classFileVersion) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Creates a new configuration where new types are named by applying the given naming strategy. By default, Byte Buddy
* simply retains the name of rebased and redefined types but adds a random suffix to the name of created subclasses or
* -interfaces. If a type is defined within the {@code java.*} namespace, Byte Buddy also adds a suffix to the generated
* class because this namespace is only available for the bootstrap class loader.
*
* @param namingStrategy The naming strategy to apply when creating a new dynamic type.
* @return A new Byte Buddy instance that uses the supplied naming strategy.
*/
public ByteBuddy with(NamingStrategy namingStrategy) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Creates a new configuration where auxiliary types are named by applying the given naming strategy. Auxiliary types
* are helper types that might be required for implementing certain {@link Implementation}s. By default, Byte Buddy
* adds a random suffix to the instrumented type's name when naming its auxiliary types.
*
* @param auxiliaryTypeNamingStrategy The naming strategy to apply when creating a new auxiliary type.
* @return A new Byte Buddy instance that uses the supplied naming strategy for auxiliary types.
*/
public ByteBuddy with(AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Creates a new configuration where annotation values are written according to the given filter factory. Using
* a filter factory, it is for example possible not to include certain values into a class file such that the
* runtime returns an annotation type's default value. By default, Byte Buddy includes all values into a class file,
* also such values for which a default value exists.
*
* @param annotationValueFilterFactory The annotation value filter factory to use.
* @return A new Byte Buddy instance that uses the supplied annotation value filter factory.
*/
public ByteBuddy with(AnnotationValueFilter.Factory annotationValueFilterFactory) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* <p>
* Creates a new configuration where annotations that are found in an existing class file are or are not preserved
* in the format they are discovered, i.e. rewritten in the format they were already present in the class file.
* By default, Byte Buddy retains annotations when a class is rebased or redefined.
* </p>
* <p>
* <b>Warning</b>: Retaining annotations can cause problems when annotations of a field or method are added based
* on the annotations of a matched method. Doing so, Byte Buddy might write the annotations of the field or method
* explicitly to a class file while simultaneously retaining the existing annotation what results in duplicates.
* When matching fields or methods while adding annotations, disabling annotation retention might be required.
* </p>
*
* @param annotationRetention The annotation retention strategy to use.
* @return A new Byte Buddy instance that uses the supplied annotation retention strategy.
*/
public ByteBuddy with(AnnotationRetention annotationRetention) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Creates a new configuration where the {@link Implementation.Context} of any created
* type is a product of the given implementation context factory. An implementation context might imply unwanted
* side-effects, for example, the creation of an additional synthetic methods in order to support specific features
* for realizing an {@link Implementation}. By default, Byte Buddy supplies a factory that enables all features. When
* redefining a loaded class, it is however required by the JVM that no additional members are added such that a
* {@link Implementation.Context.Disabled} factory might be more appropriate.
*
* @param implementationContextFactory The implementation context factory to use for defining an instrumented type.
* @return A new Byte Buddy instance that uses the supplied implementation context factory.
*/
public ByteBuddy with(Implementation.Context.Factory implementationContextFactory) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Creates a new configuration where the {@link MethodGraph.Compiler} is used for creating a {@link MethodGraph}
* of the instrumented type. A method graph is a representation of a type's virtual methods, including all information
* on bridge methods that are inserted by the Java compiler. Creating a method graph is a rather expensive operation
* and more efficient strategies might exist for certain types or ava types that are created by alternative JVM
* languages. By default, a general purpose method graph compiler is used that uses the information that is exposed
* by the generic type information that is embedded in any class file.
*
* @param methodGraphCompiler The method graph compiler to use for analyzing the instrumented type.
* @return A new Byte Buddy instance that uses the supplied method graph compiler.
*/
public ByteBuddy with(MethodGraph.Compiler methodGraphCompiler) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Configures Byte Buddy to use the specified factory for creating {@link InstrumentedType}s. Doing so, more efficient
* representations can be chosen when only certain operations are required. By default, all operations are supported.
*
* @param instrumentedTypeFactory The factory to use when creating instrumented types.
* @return A new Byte Buddy instance that uses the supplied factory for creating instrumented types.
*/
public ByteBuddy with(InstrumentedType.Factory instrumentedTypeFactory) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Creates a new configuration that applies the supplied type validation. By default, explicitly type validation is applied
* by Byte Buddy but it might be disabled for performance reason or for voluntarily creating illegal types. The Java virtual
* machine applies its own type validation where some {@link Error} is thrown if a type is invalid, while Byte Buddy throws
* some {@link RuntimeException}.
*
* @param typeValidation The type validation to apply during type creation.
* @return A new Byte Buddy instance that applies the supplied type validation.
*/
public ByteBuddy with(TypeValidation typeValidation) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* Creates a new configuration where any {@link MethodDescription} that matches the provided method matcher is excluded
* from instrumentation. Any previous matcher for ignored methods is replaced. By default, Byte Buddy ignores any
* synthetic method (bridge methods are handled automatically) and the {@link Object#finalize()} method.
*
* @param ignoredMethods A matcher for identifying methods to be excluded from instrumentation.
* @return A new Byte Buddy instance that excludes any method from instrumentation if it is matched by the supplied matcher.
*/
public ByteBuddy ignore(ElementMatcher<? super MethodDescription> ignoredMethods) {
return ignore(new LatentMatcher.Resolved<MethodDescription>(ignoredMethods));
}
/**
* <p>
* Creates a new configuration where any {@link MethodDescription} that matches the provided method matcher is excluded
* from instrumentation. Any previous matcher for ignored methods is replaced. By default, Byte Buddy ignores any
* synthetic method (bridge methods are handled automatically) and the {@link Object#finalize()} method. Using a latent
* matcher gives opportunity to resolve an {@link ElementMatcher} based on the instrumented type before applying the matcher.
* </p>
*
* @param ignoredMethods A matcher for identifying methods to be excluded from instrumentation.
* @return A new Byte Buddy instance that excludes any method from instrumentation if it is matched by the supplied matcher.
*/
public ByteBuddy ignore(LatentMatcher<? super MethodDescription> ignoredMethods) {
return new ByteBuddy(classFileVersion, namingStrategy, auxiliaryTypeNamingStrategy, annotationValueFilterFactory, annotationRetention, implementationContextFactory, methodGraphCompiler, instrumentedTypeFactory, typeValidation, ignoredMethods);
}
/**
* An implementation fo the {@code values} method of an enumeration type.
*/
protected static class EnumerationImplementation implements Implementation {
/**
* The name of the {@link java.lang.Object#clone()} method.
*/
protected static final String CLONE_METHOD_NAME = "clone";
/**
* The name of the {@code valueOf} method that is defined for any enumeration.
*/
protected static final String ENUM_VALUE_OF_METHOD_NAME = "valueOf";
/**
* The name of the {@code values} method that is defined for any enumeration.
*/
protected static final String ENUM_VALUES_METHOD_NAME = "values";
/**
* The field modifiers to use for any field that is added to an enumeration.
*/
private static final int ENUM_FIELD_MODIFIERS = Opcodes.ACC_FINAL | Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC;
/**
* The name of the field containing an array of all enumeration values.
*/
private static final String ENUM_VALUES = "$VALUES";
/**
* The names of the enumerations to define for the enumeration.
*/
private final List<String> values;
/**
* Creates a new implementation of an enumeration type.
*
* @param values The values of the enumeration.
*/
protected EnumerationImplementation(List<String> values) {
this.values = values;
}
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
for (String value : values) {
instrumentedType = instrumentedType.withField(new FieldDescription.Token(value, ENUM_FIELD_MODIFIERS | Opcodes.ACC_ENUM, TargetType.DESCRIPTION.asGenericType()));
}
return instrumentedType.withField(new FieldDescription.Token(ENUM_VALUES, ENUM_FIELD_MODIFIERS | Opcodes.ACC_SYNTHETIC, TypeDescription.ArrayProjection.of(TargetType.DESCRIPTION).asGenericType())).withInitializer(new InitializationAppender(values));
}
@Override
public ByteCodeAppender appender(Target implementationTarget) {
return new ValuesMethodAppender(implementationTarget.getInstrumentedType());
}
/**
* A byte code appender for the {@code values} method of any enumeration type.
*/
protected static class ValuesMethodAppender implements ByteCodeAppender {
/**
* The instrumented enumeration type.
*/
private final TypeDescription instrumentedType;
/**
* Creates a new appender for the {@code values} method.
*
* @param instrumentedType The instrumented enumeration type.
*/
protected ValuesMethodAppender(TypeDescription instrumentedType) {
this.instrumentedType = instrumentedType;
}
@Override
public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
FieldDescription valuesField = instrumentedType.getDeclaredFields().filter(ElementMatchers.named(ENUM_VALUES)).getOnly();
MethodDescription cloneMethod = TypeDescription.Generic.OBJECT.getDeclaredMethods().filter(ElementMatchers.named(CLONE_METHOD_NAME)).getOnly();
return new Size(new StackManipulation.Compound(FieldAccess.forField(valuesField).read(), MethodInvocation.invoke(cloneMethod).virtual(valuesField.getType().asErasure()), TypeCasting.to(valuesField.getType().asErasure()), MethodReturn.REFERENCE).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ByteBuddy.EnumerationImplementation.ValuesMethodAppender)) return false;
final ByteBuddy.EnumerationImplementation.ValuesMethodAppender other = (ByteBuddy.EnumerationImplementation.ValuesMethodAppender) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$instrumentedType = this.instrumentedType;
final java.lang.Object other$instrumentedType = other.instrumentedType;
if (this$instrumentedType == null ? other$instrumentedType != null : !this$instrumentedType.equals(other$instrumentedType))
return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ByteBuddy.EnumerationImplementation.ValuesMethodAppender;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $instrumentedType = this.instrumentedType;
result = result * PRIME + ($instrumentedType == null ? 43 : $instrumentedType.hashCode());
return result;
}
}
/**
* A byte code appender for the type initializer of any enumeration type.
*/
protected static class InitializationAppender implements ByteCodeAppender {
/**
* The values of the enumeration that is being created.
*/
private final List<String> values;
/**
* Creates an appender for an enumerations type initializer.
*
* @param values The values of the enumeration that is being created.
*/
protected InitializationAppender(List<String> values) {
this.values = values;
}
@Override
public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
TypeDescription instrumentedType = instrumentedMethod.getDeclaringType().asErasure();
MethodDescription enumConstructor = instrumentedType.getDeclaredMethods().filter(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class, int.class))).getOnly();
int ordinal = 0;
StackManipulation stackManipulation = StackManipulation.Trivial.INSTANCE;
List<FieldDescription> enumerationFields = new ArrayList<FieldDescription>(values.size());
for (String value : values) {
FieldDescription fieldDescription = instrumentedType.getDeclaredFields().filter(ElementMatchers.named(value)).getOnly();
stackManipulation = new StackManipulation.Compound(stackManipulation, TypeCreation.of(instrumentedType), Duplication.SINGLE, new TextConstant(value), IntegerConstant.forValue(ordinal++), MethodInvocation.invoke(enumConstructor), FieldAccess.forField(fieldDescription).write());
enumerationFields.add(fieldDescription);
}
List<StackManipulation> fieldGetters = new ArrayList<StackManipulation>(values.size());
for (FieldDescription fieldDescription : enumerationFields) {
fieldGetters.add(FieldAccess.forField(fieldDescription).read());
}
stackManipulation = new StackManipulation.Compound(stackManipulation, ArrayFactory.forType(instrumentedType.asGenericType()).withValues(fieldGetters), FieldAccess.forField(instrumentedType.getDeclaredFields().filter(ElementMatchers.named(ENUM_VALUES)).getOnly()).write());
return new Size(stackManipulation.apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ByteBuddy.EnumerationImplementation.InitializationAppender)) return false;
final ByteBuddy.EnumerationImplementation.InitializationAppender other = (ByteBuddy.EnumerationImplementation.InitializationAppender) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$values = this.values;
final java.lang.Object other$values = other.values;
if (this$values == null ? other$values != null : !this$values.equals(other$values)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ByteBuddy.EnumerationImplementation.InitializationAppender;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $values = this.values;
result = result * PRIME + ($values == null ? 43 : $values.hashCode());
return result;
}
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ByteBuddy.EnumerationImplementation)) return false;
final ByteBuddy.EnumerationImplementation other = (ByteBuddy.EnumerationImplementation) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$values = this.values;
final java.lang.Object other$values = other.values;
if (this$values == null ? other$values != null : !this$values.equals(other$values)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ByteBuddy.EnumerationImplementation;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $values = this.values;
result = result * PRIME + ($values == null ? 43 : $values.hashCode());
return result;
}
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ByteBuddy)) return false;
final ByteBuddy other = (ByteBuddy) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$classFileVersion = this.classFileVersion;
final java.lang.Object other$classFileVersion = other.classFileVersion;
if (this$classFileVersion == null ? other$classFileVersion != null : !this$classFileVersion.equals(other$classFileVersion))
return false;
final java.lang.Object this$namingStrategy = this.namingStrategy;
final java.lang.Object other$namingStrategy = other.namingStrategy;
if (this$namingStrategy == null ? other$namingStrategy != null : !this$namingStrategy.equals(other$namingStrategy))
return false;
final java.lang.Object this$auxiliaryTypeNamingStrategy = this.auxiliaryTypeNamingStrategy;
final java.lang.Object other$auxiliaryTypeNamingStrategy = other.auxiliaryTypeNamingStrategy;
if (this$auxiliaryTypeNamingStrategy == null ? other$auxiliaryTypeNamingStrategy != null : !this$auxiliaryTypeNamingStrategy.equals(other$auxiliaryTypeNamingStrategy))
return false;
final java.lang.Object this$annotationValueFilterFactory = this.annotationValueFilterFactory;
final java.lang.Object other$annotationValueFilterFactory = other.annotationValueFilterFactory;
if (this$annotationValueFilterFactory == null ? other$annotationValueFilterFactory != null : !this$annotationValueFilterFactory.equals(other$annotationValueFilterFactory))
return false;
final java.lang.Object this$annotationRetention = this.annotationRetention;
final java.lang.Object other$annotationRetention = other.annotationRetention;
if (this$annotationRetention == null ? other$annotationRetention != null : !this$annotationRetention.equals(other$annotationRetention))
return false;
final java.lang.Object this$implementationContextFactory = this.implementationContextFactory;
final java.lang.Object other$implementationContextFactory = other.implementationContextFactory;
if (this$implementationContextFactory == null ? other$implementationContextFactory != null : !this$implementationContextFactory.equals(other$implementationContextFactory))
return false;
final java.lang.Object this$methodGraphCompiler = this.methodGraphCompiler;
final java.lang.Object other$methodGraphCompiler = other.methodGraphCompiler;
if (this$methodGraphCompiler == null ? other$methodGraphCompiler != null : !this$methodGraphCompiler.equals(other$methodGraphCompiler))
return false;
final java.lang.Object this$instrumentedTypeFactory = this.instrumentedTypeFactory;
final java.lang.Object other$instrumentedTypeFactory = other.instrumentedTypeFactory;
if (this$instrumentedTypeFactory == null ? other$instrumentedTypeFactory != null : !this$instrumentedTypeFactory.equals(other$instrumentedTypeFactory))
return false;
final java.lang.Object this$ignoredMethods = this.ignoredMethods;
final java.lang.Object other$ignoredMethods = other.ignoredMethods;
if (this$ignoredMethods == null ? other$ignoredMethods != null : !this$ignoredMethods.equals(other$ignoredMethods))
return false;
final java.lang.Object this$typeValidation = this.typeValidation;
final java.lang.Object other$typeValidation = other.typeValidation;
if (this$typeValidation == null ? other$typeValidation != null : !this$typeValidation.equals(other$typeValidation))
return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ByteBuddy;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $classFileVersion = this.classFileVersion;
result = result * PRIME + ($classFileVersion == null ? 43 : $classFileVersion.hashCode());
final java.lang.Object $namingStrategy = this.namingStrategy;
result = result * PRIME + ($namingStrategy == null ? 43 : $namingStrategy.hashCode());
final java.lang.Object $auxiliaryTypeNamingStrategy = this.auxiliaryTypeNamingStrategy;
result = result * PRIME + ($auxiliaryTypeNamingStrategy == null ? 43 : $auxiliaryTypeNamingStrategy.hashCode());
final java.lang.Object $annotationValueFilterFactory = this.annotationValueFilterFactory;
result = result * PRIME + ($annotationValueFilterFactory == null ? 43 : $annotationValueFilterFactory.hashCode());
final java.lang.Object $annotationRetention = this.annotationRetention;
result = result * PRIME + ($annotationRetention == null ? 43 : $annotationRetention.hashCode());
final java.lang.Object $implementationContextFactory = this.implementationContextFactory;
result = result * PRIME + ($implementationContextFactory == null ? 43 : $implementationContextFactory.hashCode());
final java.lang.Object $methodGraphCompiler = this.methodGraphCompiler;
result = result * PRIME + ($methodGraphCompiler == null ? 43 : $methodGraphCompiler.hashCode());
final java.lang.Object $instrumentedTypeFactory = this.instrumentedTypeFactory;
result = result * PRIME + ($instrumentedTypeFactory == null ? 43 : $instrumentedTypeFactory.hashCode());
final java.lang.Object $ignoredMethods = this.ignoredMethods;
result = result * PRIME + ($ignoredMethods == null ? 43 : $ignoredMethods.hashCode());
final java.lang.Object $typeValidation = this.typeValidation;
result = result * PRIME + ($typeValidation == null ? 43 : $typeValidation.hashCode());
return result;
}
}