package net.bytebuddy.dynamic.scaffold.inline;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.modifier.ModifierContributor;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeVariableToken;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.Transformer;
import net.bytebuddy.dynamic.TypeResolutionStrategy;
import net.bytebuddy.dynamic.scaffold.ClassWriterStrategy;
import net.bytebuddy.dynamic.scaffold.MethodGraph;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.dynamic.scaffold.TypeWriter;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.LoadedTypeInitializer;
import net.bytebuddy.implementation.attribute.AnnotationRetention;
import net.bytebuddy.implementation.attribute.AnnotationValueFilter;
import net.bytebuddy.implementation.attribute.TypeAttributeAppender;
import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.LatentMatcher;
import net.bytebuddy.pool.TypePool;
import net.bytebuddy.utility.CompoundList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static net.bytebuddy.matcher.ElementMatchers.isVirtual;
import static net.bytebuddy.matcher.ElementMatchers.not;
@HashCodeAndEqualsPlugin.Enhance
public class DecoratingDynamicTypeBuilder<T> extends DynamicType.Builder.AbstractBase<T> {
private final TypeDescription instrumentedType;
private final TypeAttributeAppender typeAttributeAppender;
private final AsmVisitorWrapper asmVisitorWrapper;
private final ClassFileVersion classFileVersion;
private final AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy;
private final AnnotationValueFilter.Factory annotationValueFilterFactory;
private final AnnotationRetention annotationRetention;
private final Implementation.Context.Factory implementationContextFactory;
private final MethodGraph.Compiler methodGraphCompiler;
private final TypeValidation typeValidation;
private final ClassWriterStrategy classWriterStrategy;
private final LatentMatcher<? super MethodDescription> ignoredMethods;
private final List<DynamicType> auxiliaryTypes;
private final ClassFileLocator classFileLocator;
public DecoratingDynamicTypeBuilder(TypeDescription instrumentedType,
ClassFileVersion classFileVersion,
AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
AnnotationValueFilter.Factory annotationValueFilterFactory,
AnnotationRetention annotationRetention,
Implementation.Context.Factory implementationContextFactory,
MethodGraph.Compiler methodGraphCompiler,
TypeValidation typeValidation,
ClassWriterStrategy classWriterStrategy,
LatentMatcher<? super MethodDescription> ignoredMethods,
ClassFileLocator classFileLocator) {
this(instrumentedType,
annotationRetention.isEnabled()
? new TypeAttributeAppender.ForInstrumentedType.Differentiating(instrumentedType)
: TypeAttributeAppender.ForInstrumentedType.INSTANCE,
AsmVisitorWrapper.NoOp.INSTANCE,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
Collections.<DynamicType>emptyList(),
classFileLocator);
}
protected DecoratingDynamicTypeBuilder(TypeDescription instrumentedType,
TypeAttributeAppender typeAttributeAppender,
AsmVisitorWrapper asmVisitorWrapper,
ClassFileVersion classFileVersion,
AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
AnnotationValueFilter.Factory annotationValueFilterFactory,
AnnotationRetention annotationRetention,
Implementation.Context.Factory implementationContextFactory,
MethodGraph.Compiler methodGraphCompiler,
TypeValidation typeValidation,
ClassWriterStrategy classWriterStrategy,
LatentMatcher<? super MethodDescription> ignoredMethods,
List<DynamicType> auxiliaryTypes,
ClassFileLocator classFileLocator) {
this.instrumentedType = instrumentedType;
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;
this.classFileLocator = classFileLocator;
}
public DynamicType.Builder<T> visit(AsmVisitorWrapper asmVisitorWrapper) {
return new DecoratingDynamicTypeBuilder<T>(instrumentedType,
typeAttributeAppender,
new AsmVisitorWrapper.Compound(this.asmVisitorWrapper, asmVisitorWrapper),
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes,
classFileLocator);
}
public DynamicType.Builder<T> name(String name) {
throw new UnsupportedOperationException("Cannot change name of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> modifiers(int modifiers) {
throw new UnsupportedOperationException("Cannot change modifiers of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> merge(Collection<? extends ModifierContributor.ForType> modifierContributors) {
throw new UnsupportedOperationException("Cannot change modifiers of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> topLevelType() {
throw new UnsupportedOperationException("Cannot change type declaration of decorated type: " + instrumentedType);
}
public InnerTypeDefinition.ForType<T> innerTypeOf(TypeDescription type) {
throw new UnsupportedOperationException("Cannot change type declaration of decorated type: " + instrumentedType);
}
public InnerTypeDefinition<T> innerTypeOf(MethodDescription.InDefinedShape methodDescription) {
throw new UnsupportedOperationException("Cannot change type declaration of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> declaredTypes(Collection<? extends TypeDescription> types) {
throw new UnsupportedOperationException("Cannot change type declaration of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> nestHost(TypeDescription type) {
throw new UnsupportedOperationException("Cannot change type declaration of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> nestMembers(Collection<? extends TypeDescription> types) {
throw new UnsupportedOperationException("Cannot change type declaration of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> attribute(TypeAttributeAppender typeAttributeAppender) {
return new DecoratingDynamicTypeBuilder<T>(instrumentedType,
new TypeAttributeAppender.Compound(this.typeAttributeAppender, typeAttributeAppender),
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
auxiliaryTypes,
classFileLocator);
}
public DynamicType.Builder<T> annotateType(Collection<? extends AnnotationDescription> annotations) {
return attribute(new TypeAttributeAppender.Explicit(new ArrayList<AnnotationDescription>(annotations)));
}
public MethodDefinition.ImplementationDefinition.Optional<T> implement(Collection<? extends TypeDefinition> interfaceTypes) {
throw new UnsupportedOperationException("Cannot implement interface for decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> initializer(ByteCodeAppender byteCodeAppender) {
throw new UnsupportedOperationException("Cannot add initializer of decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> initializer(LoadedTypeInitializer loadedTypeInitializer) {
throw new UnsupportedOperationException("Cannot add initializer of decorated type: " + instrumentedType);
}
public TypeVariableDefinition<T> typeVariable(String symbol, Collection<? extends TypeDefinition> bounds) {
throw new UnsupportedOperationException("Cannot add type variable to decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> transform(ElementMatcher<? super TypeDescription.Generic> matcher, Transformer<TypeVariableToken> transformer) {
throw new UnsupportedOperationException("Cannot transform decorated type: " + instrumentedType);
}
public FieldDefinition.Optional.Valuable<T> defineField(String name, TypeDefinition type, int modifiers) {
throw new UnsupportedOperationException("Cannot define field for decorated type: " + instrumentedType);
}
public FieldDefinition.Valuable<T> field(LatentMatcher<? super FieldDescription> matcher) {
throw new UnsupportedOperationException("Cannot change field for decorated type: " + instrumentedType);
}
@SuppressWarnings("unchecked")
public DynamicType.Builder<T> ignoreAlso(LatentMatcher<? super MethodDescription> ignoredMethods) {
return new DecoratingDynamicTypeBuilder<T>(instrumentedType,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
new LatentMatcher.Disjunction<MethodDescription>(this.ignoredMethods, ignoredMethods),
auxiliaryTypes,
classFileLocator);
}
public MethodDefinition.ParameterDefinition.Initial<T> defineMethod(String name, TypeDefinition returnType, int modifiers) {
throw new UnsupportedOperationException("Cannot define method for decorated type: " + instrumentedType);
}
public MethodDefinition.ParameterDefinition.Initial<T> defineConstructor(int modifiers) {
throw new UnsupportedOperationException("Cannot define constructor for decorated type: " + instrumentedType);
}
public MethodDefinition.ImplementationDefinition<T> invokable(LatentMatcher<? super MethodDescription> matcher) {
throw new UnsupportedOperationException("Cannot intercept method for decorated type: " + instrumentedType);
}
public DynamicType.Builder<T> require(Collection<DynamicType> auxiliaryTypes) {
return new DecoratingDynamicTypeBuilder<T>(instrumentedType,
typeAttributeAppender,
asmVisitorWrapper,
classFileVersion,
auxiliaryTypeNamingStrategy,
annotationValueFilterFactory,
annotationRetention,
implementationContextFactory,
methodGraphCompiler,
typeValidation,
classWriterStrategy,
ignoredMethods,
CompoundList.of(this.auxiliaryTypes, new ArrayList<DynamicType>(auxiliaryTypes)),
classFileLocator);
}
public DynamicType.Unloaded<T> make(TypeResolutionStrategy typeResolutionStrategy) {
return make(typeResolutionStrategy, TypePool.Empty.INSTANCE);
}
public DynamicType.Unloaded<T> make(TypeResolutionStrategy typeResolutionStrategy, TypePool typePool) {
return TypeWriter.Default.<T>forDecoration(instrumentedType,
classFileVersion,
auxiliaryTypes,
CompoundList.of(methodGraphCompiler.compile(instrumentedType)
.listNodes()
.asMethodList()
.filter(not(ignoredMethods.resolve(instrumentedType))), instrumentedType.getDeclaredMethods().filter(not(isVirtual()))),
typeAttributeAppender,
asmVisitorWrapper,
annotationValueFilterFactory,
annotationRetention,
auxiliaryTypeNamingStrategy,
implementationContextFactory,
typeValidation,
classWriterStrategy,
typePool,
classFileLocator).make(typeResolutionStrategy.resolve());
}
}