// Generated by delombok at Sun Feb 26 12:31:38 KST 2017
package scouter.bytebuddy.dynamic.scaffold;
import scouter.bytebuddy.ClassFileVersion;
import scouter.bytebuddy.description.annotation.AnnotationValue;
import scouter.bytebuddy.description.method.MethodDescription;
import scouter.bytebuddy.description.method.MethodList;
import scouter.bytebuddy.description.modifier.Visibility;
import scouter.bytebuddy.description.type.TypeDescription;
import scouter.bytebuddy.dynamic.Transformer;
import scouter.bytebuddy.implementation.Implementation;
import scouter.bytebuddy.implementation.LoadedTypeInitializer;
import scouter.bytebuddy.implementation.attribute.MethodAttributeAppender;
import scouter.bytebuddy.implementation.bytecode.ByteCodeAppender;
import scouter.bytebuddy.matcher.ElementMatcher;
import scouter.bytebuddy.matcher.LatentMatcher;
import scouter.bytebuddy.utility.CompoundList;
import scouter.bytebuddy.matcher.ElementMatchers;
import java.util.*;
import static scouter.bytebuddy.matcher.ElementMatchers.*;
/**
* A method registry is responsible for storing information on how a method is intercepted.
*/
public interface MethodRegistry {
/**
* Prepends the given method definition to this method registry, i.e. this configuration is applied first.
*
* @param methodMatcher A matcher to identify any method that this definition concerns.
* @param handler The handler to instrument any matched method.
* @param attributeAppenderFactory A method attribute appender to apply to any matched method.
* @param transformer The method transformer to be applied to implemented methods.
* @return An adapted version of this method registry.
*/
MethodRegistry prepend(LatentMatcher<? super MethodDescription> methodMatcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer);
/**
* Appends the given method definition to this method registry, i.e. this configuration is applied last.
*
* @param methodMatcher A matcher to identify all entries that are to be matched.
* @param handler The handler to instrument any matched method.
* @param attributeAppenderFactory A method attribute appender to apply to any matched method.
* @param transformer The method transformer to be applied to implemented methods.
* @return An adapted version of this method registry.
*/
MethodRegistry append(LatentMatcher<? super MethodDescription> methodMatcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer);
/**
* Prepares this method registry.
*
* @param instrumentedType The instrumented type that should be created.
* @param methodGraphCompiler The method graph compiler to be used for analyzing the fully assembled instrumented type.
* @param typeValidation Determines if a type should be explicitly validated.
* @param ignoredMethods A filter that only matches methods that should be instrumented.
* @return A prepared version of this method registry.
*/
Prepared prepare(InstrumentedType instrumentedType, MethodGraph.Compiler methodGraphCompiler, TypeValidation typeValidation, LatentMatcher<? super MethodDescription> ignoredMethods);
/**
* A handler for implementing a method.
*/
interface Handler extends InstrumentedType.Prepareable {
/**
* Compiles this handler.
*
* @param implementationTarget The implementation target to compile this handler for.
* @return A compiled handler.
*/
Handler.Compiled compile(Implementation.Target implementationTarget);
/**
* A handler for defining an abstract or native method.
*/
enum ForAbstractMethod implements Handler, Compiled {
/**
* The singleton instance.
*/
INSTANCE;
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
return instrumentedType;
}
@Override
public Compiled compile(Implementation.Target implementationTarget) {
return this;
}
@Override
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) {
return new TypeWriter.MethodPool.Record.ForDefinedMethod.WithoutBody(methodDescription, attributeAppender, visibility);
}
}
/**
* A handler for implementing a visibility bridge.
*/
enum ForVisibilityBridge implements Handler {
/**
* The singleton instance.
*/
INSTANCE;
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
throw new IllegalStateException("A visibility bridge handler must not apply any preparations");
}
@Override
public Compiled compile(Implementation.Target implementationTarget) {
return new Compiled(implementationTarget.getInstrumentedType());
}
/**
* A compiled handler for a visibility bridge handler.
*/
protected static class Compiled implements Handler.Compiled {
/**
* The instrumented type.
*/
private final TypeDescription instrumentedType;
/**
* Creates a new compiled handler for a visibility bridge.
*
* @param instrumentedType The instrumented type.
*/
protected Compiled(TypeDescription instrumentedType) {
this.instrumentedType = instrumentedType;
}
@Override
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) {
return TypeWriter.MethodPool.Record.ForDefinedMethod.OfVisibilityBridge.of(instrumentedType, methodDescription, attributeAppender);
}
@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 MethodRegistry.Handler.ForVisibilityBridge.Compiled)) return false;
final MethodRegistry.Handler.ForVisibilityBridge.Compiled other = (MethodRegistry.Handler.ForVisibilityBridge.Compiled) 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 MethodRegistry.Handler.ForVisibilityBridge.Compiled;
}
@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 compiled handler for implementing a method.
*/
interface Compiled {
/**
* Assembles this compiled entry with a method attribute appender.
*
* @param methodDescription The method description to apply with this handler.
* @param attributeAppender The method attribute appender to apply together with this handler.
* @param visibility The represented method's minimum visibility.
* @return A method pool entry representing this handler and the given attribute appender.
*/
TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility);
}
/**
* A handler for a method that is implemented as byte code.
*/
class ForImplementation implements Handler {
/**
* The implementation to apply.
*/
private final Implementation implementation;
/**
* Creates a new handler for implementing a method with byte code.
*
* @param implementation The implementation to apply.
*/
public ForImplementation(Implementation implementation) {
this.implementation = implementation;
}
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
return implementation.prepare(instrumentedType);
}
@Override
public Compiled compile(Implementation.Target implementationTarget) {
return new Compiled(implementation.appender(implementationTarget));
}
/**
* A compiled handler for implementing a method.
*/
protected static class Compiled implements Handler.Compiled {
/**
* The byte code appender to apply.
*/
private final ByteCodeAppender byteCodeAppender;
/**
* Creates a new compiled handler for a method implementation.
*
* @param byteCodeAppender The byte code appender to apply.
*/
protected Compiled(ByteCodeAppender byteCodeAppender) {
this.byteCodeAppender = byteCodeAppender;
}
@Override
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) {
return new TypeWriter.MethodPool.Record.ForDefinedMethod.WithBody(methodDescription, byteCodeAppender, attributeAppender, visibility);
}
@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 MethodRegistry.Handler.ForImplementation.Compiled)) return false;
final MethodRegistry.Handler.ForImplementation.Compiled other = (MethodRegistry.Handler.ForImplementation.Compiled) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$byteCodeAppender = this.byteCodeAppender;
final java.lang.Object other$byteCodeAppender = other.byteCodeAppender;
if (this$byteCodeAppender == null ? other$byteCodeAppender != null : !this$byteCodeAppender.equals(other$byteCodeAppender)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Handler.ForImplementation.Compiled;
}
@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 $byteCodeAppender = this.byteCodeAppender;
result = result * PRIME + ($byteCodeAppender == null ? 43 : $byteCodeAppender.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 MethodRegistry.Handler.ForImplementation)) return false;
final MethodRegistry.Handler.ForImplementation other = (MethodRegistry.Handler.ForImplementation) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$implementation = this.implementation;
final java.lang.Object other$implementation = other.implementation;
if (this$implementation == null ? other$implementation != null : !this$implementation.equals(other$implementation)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Handler.ForImplementation;
}
@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 $implementation = this.implementation;
result = result * PRIME + ($implementation == null ? 43 : $implementation.hashCode());
return result;
}
}
/**
* A handler for defining a default annotation value for a method.
*/
class ForAnnotationValue implements Handler, Compiled {
/**
* The annotation value to set as a default value.
*/
private final AnnotationValue<?, ?> annotationValue;
/**
* Creates a handler for defining a default annotation value for a method.
*
* @param annotationValue The annotation value to set as a default value.
*/
public ForAnnotationValue(AnnotationValue<?, ?> annotationValue) {
this.annotationValue = annotationValue;
}
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
return instrumentedType;
}
@Override
public Compiled compile(Implementation.Target implementationTarget) {
return this;
}
@Override
public TypeWriter.MethodPool.Record assemble(MethodDescription methodDescription, MethodAttributeAppender attributeAppender, Visibility visibility) {
return new TypeWriter.MethodPool.Record.ForDefinedMethod.WithAnnotationDefaultValue(methodDescription, annotationValue, attributeAppender);
}
@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 MethodRegistry.Handler.ForAnnotationValue)) return false;
final MethodRegistry.Handler.ForAnnotationValue other = (MethodRegistry.Handler.ForAnnotationValue) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$annotationValue = this.annotationValue;
final java.lang.Object other$annotationValue = other.annotationValue;
if (this$annotationValue == null ? other$annotationValue != null : !this$annotationValue.equals(other$annotationValue)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Handler.ForAnnotationValue;
}
@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 $annotationValue = this.annotationValue;
result = result * PRIME + ($annotationValue == null ? 43 : $annotationValue.hashCode());
return result;
}
}
}
/**
* A method registry that fully prepared the instrumented type.
*/
interface Prepared {
/**
* Returns the fully prepared instrumented type.
*
* @return The fully prepared instrumented type.
*/
TypeDescription getInstrumentedType();
/**
* Returns the declared or virtually inherited methods of this type.
*
* @return The declared or virtually inherited methods of this type.
*/
MethodList<?> getMethods();
/**
* Returns a list of all methods that should be instrumented.
*
* @return A list of all methods that should be instrumented.
*/
MethodList<?> getInstrumentedMethods();
/**
* Returns the loaded type initializer of the instrumented type.
*
* @return The loaded type initializer of the instrumented type.
*/
LoadedTypeInitializer getLoadedTypeInitializer();
/**
* The type initializer of the instrumented type.
*
* @return The type initializer of the instrumented type.
*/
TypeInitializer getTypeInitializer();
/**
* Compiles this prepared method registry.
*
* @param implementationTargetFactory A factory for creating an implementation target.
* @param classFileVersion The type's class file version.
* @return A factory for creating an implementation target.
*/
Compiled compile(Implementation.Target.Factory implementationTargetFactory, ClassFileVersion classFileVersion);
}
/**
* A compiled version of a method registry.
*/
interface Compiled extends TypeWriter.MethodPool {
/**
* Returns the instrumented type that is to be created.
*
* @return The instrumented type that is to be created.
*/
TypeDescription getInstrumentedType();
/**
* Returns the declared or virtually inherited methods of this type.
*
* @return The declared or virtually inherited methods of this type.
*/
MethodList<?> getMethods();
/**
* Returns a list of all methods that should be instrumented.
*
* @return A list of all methods that should be instrumented.
*/
MethodList<?> getInstrumentedMethods();
/**
* Returns the loaded type initializer of the instrumented type.
*
* @return The loaded type initializer of the instrumented type.
*/
LoadedTypeInitializer getLoadedTypeInitializer();
/**
* The type initializer of the instrumented type.
*
* @return The type initializer of the instrumented type.
*/
TypeInitializer getTypeInitializer();
}
/**
* A default implementation of a method registry.
*/
class Default implements MethodRegistry {
/**
* The list of currently registered entries in their application order.
*/
private final List<Entry> entries;
/**
* Creates a new default method registry without entries.
*/
public Default() {
entries = Collections.emptyList();
}
/**
* Creates a new default method registry.
*
* @param entries The currently registered entries.
*/
private Default(List<Entry> entries) {
this.entries = entries;
}
@Override
public MethodRegistry prepend(LatentMatcher<? super MethodDescription> matcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer) {
return new Default(CompoundList.of(new Entry(matcher, handler, attributeAppenderFactory, transformer), entries));
}
@Override
public MethodRegistry append(LatentMatcher<? super MethodDescription> matcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer) {
return new Default(CompoundList.of(entries, new Entry(matcher, handler, attributeAppenderFactory, transformer)));
}
@Override
public MethodRegistry.Prepared prepare(InstrumentedType instrumentedType, MethodGraph.Compiler methodGraphCompiler, TypeValidation typeValidation, LatentMatcher<? super MethodDescription> ignoredMethods) {
LinkedHashMap<MethodDescription, Prepared.Entry> implementations = new LinkedHashMap<MethodDescription, Prepared.Entry>();
Set<Handler> handlers = new HashSet<Handler>();
MethodList<?> helperMethods = instrumentedType.getDeclaredMethods();
for (Entry entry : entries) {
if (handlers.add(entry.getHandler())) {
instrumentedType = entry.getHandler().prepare(instrumentedType);
ElementMatcher<? super MethodDescription> handledMethods = noneOf(helperMethods);
helperMethods = instrumentedType.getDeclaredMethods();
for (MethodDescription helperMethod : helperMethods.filter(handledMethods)) {
implementations.put(helperMethod, entry.asSupplementaryEntry(helperMethod));
}
}
}
MethodGraph.Linked methodGraph = methodGraphCompiler.compile(instrumentedType);
// Casting required for Java 6 compiler.
ElementMatcher<? super MethodDescription> relevanceMatcher = (ElementMatcher<? super MethodDescription>) ElementMatchers.not(ElementMatchers.anyOf(implementations.keySet())).and(returns(isVisibleTo(instrumentedType))).and(ElementMatchers.hasParameters(ElementMatchers.whereNone(ElementMatchers.hasType(ElementMatchers.not(isVisibleTo(instrumentedType)))))).and(ignoredMethods.resolve(instrumentedType));
List<MethodDescription> methods = new ArrayList<MethodDescription>();
for (MethodGraph.Node node : methodGraph.listNodes()) {
MethodDescription methodDescription = node.getRepresentative();
boolean visibilityBridge = instrumentedType.isPublic() && !instrumentedType.isInterface();
if (relevanceMatcher.matches(methodDescription)) {
for (Entry entry : entries) {
if (entry.resolve(instrumentedType).matches(methodDescription)) {
implementations.put(methodDescription, entry.asPreparedEntry(instrumentedType, methodDescription, node.getMethodTypes(), node.getVisibility()));
visibilityBridge = false;
break;
}
}
}
if (visibilityBridge && !node.getSort().isMadeVisible() && methodDescription.isPublic() && !(methodDescription.isAbstract() || methodDescription.isFinal()) && methodDescription.getDeclaringType().isPackagePrivate()) {
// Visibility bridges are required for public classes that inherit a public method from a package-private class.
implementations.put(methodDescription, Prepared.Entry.forVisibilityBridge(methodDescription, node.getVisibility()));
}
methods.add(methodDescription);
}
for (MethodDescription methodDescription : CompoundList.of(instrumentedType.getDeclaredMethods().filter(ElementMatchers.not(ElementMatchers.isVirtual()).and(relevanceMatcher)), new MethodDescription.Latent.TypeInitializer(instrumentedType))) {
for (Entry entry : entries) {
if (entry.resolve(instrumentedType).matches(methodDescription)) {
implementations.put(methodDescription, entry.asPreparedEntry(instrumentedType, methodDescription, methodDescription.getVisibility()));
break;
}
}
methods.add(methodDescription);
}
return new Prepared(implementations, instrumentedType.getLoadedTypeInitializer(), instrumentedType.getTypeInitializer(), typeValidation.isEnabled() ? instrumentedType.validated() : instrumentedType, methodGraph, new MethodList.Explicit<MethodDescription>(methods));
}
/**
* An entry of a default method registry.
*/
protected static class Entry implements LatentMatcher<MethodDescription> {
/**
* The latent method matcher that this entry represents.
*/
private final LatentMatcher<? super MethodDescription> matcher;
/**
* The handler to apply to all matched entries.
*/
private final Handler handler;
/**
* A method attribute appender factory to apply to all entries.
*/
private final MethodAttributeAppender.Factory attributeAppenderFactory;
/**
* The method transformer to be applied to implemented methods.
*/
private final Transformer<MethodDescription> transformer;
/**
* Creates a new entry.
*
* @param matcher The latent method matcher that this entry represents.
* @param handler The handler to apply to all matched entries.
* @param attributeAppenderFactory A method attribute appender factory to apply to all entries.
* @param transformer The method transformer to be applied to implemented methods.
*/
protected Entry(LatentMatcher<? super MethodDescription> matcher, Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, Transformer<MethodDescription> transformer) {
this.matcher = matcher;
this.handler = handler;
this.attributeAppenderFactory = attributeAppenderFactory;
this.transformer = transformer;
}
/**
* Transforms this entry into a prepared state.
*
* @param instrumentedType The instrumented type.
* @param methodDescription The non-transformed method to be implemented.
* @param visibility The represented method's minimum visibility.
* @return A prepared version of this entry.
*/
protected Prepared.Entry asPreparedEntry(TypeDescription instrumentedType, MethodDescription methodDescription, Visibility visibility) {
return asPreparedEntry(instrumentedType, methodDescription, Collections.<MethodDescription.TypeToken>emptySet(), visibility);
}
/**
* Transforms this entry into a prepared state.
*
* @param instrumentedType The instrumented type.
* @param methodDescription The non-transformed method to be implemented.
* @param methodTypes The method types this method represents.
* @param visibility The represented method's minimum visibility.
* @return A prepared version of this entry.
*/
protected Prepared.Entry asPreparedEntry(TypeDescription instrumentedType, MethodDescription methodDescription, Set<MethodDescription.TypeToken> methodTypes, Visibility visibility) {
return new Prepared.Entry(handler, attributeAppenderFactory, transformer.transform(instrumentedType, methodDescription), methodTypes, visibility, false);
}
/**
* Returns a prepared entry for a supplementary method.
*
* @param methodDescription The method to be implemented.
* @return An entry for a supplementary entry that is defined by a method implementation instance.
*/
protected Prepared.Entry asSupplementaryEntry(MethodDescription methodDescription) {
return new Prepared.Entry(handler, MethodAttributeAppender.Explicit.of(methodDescription), methodDescription, Collections.<MethodDescription.TypeToken>emptySet(), methodDescription.getVisibility(), false);
}
/**
* Returns this entry's handler.
*
* @return The handler of this entry.
*/
protected Handler getHandler() {
return handler;
}
@Override
public ElementMatcher<? super MethodDescription> resolve(TypeDescription typeDescription) {
return matcher.resolve(typeDescription);
}
@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 MethodRegistry.Default.Entry)) return false;
final MethodRegistry.Default.Entry other = (MethodRegistry.Default.Entry) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$matcher = this.matcher;
final java.lang.Object other$matcher = other.matcher;
if (this$matcher == null ? other$matcher != null : !this$matcher.equals(other$matcher)) return false;
final java.lang.Object this$handler = this.getHandler();
final java.lang.Object other$handler = other.getHandler();
if (this$handler == null ? other$handler != null : !this$handler.equals(other$handler)) return false;
final java.lang.Object this$attributeAppenderFactory = this.attributeAppenderFactory;
final java.lang.Object other$attributeAppenderFactory = other.attributeAppenderFactory;
if (this$attributeAppenderFactory == null ? other$attributeAppenderFactory != null : !this$attributeAppenderFactory.equals(other$attributeAppenderFactory)) return false;
final java.lang.Object this$transformer = this.transformer;
final java.lang.Object other$transformer = other.transformer;
if (this$transformer == null ? other$transformer != null : !this$transformer.equals(other$transformer)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Default.Entry;
}
@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 $matcher = this.matcher;
result = result * PRIME + ($matcher == null ? 43 : $matcher.hashCode());
final java.lang.Object $handler = this.getHandler();
result = result * PRIME + ($handler == null ? 43 : $handler.hashCode());
final java.lang.Object $attributeAppenderFactory = this.attributeAppenderFactory;
result = result * PRIME + ($attributeAppenderFactory == null ? 43 : $attributeAppenderFactory.hashCode());
final java.lang.Object $transformer = this.transformer;
result = result * PRIME + ($transformer == null ? 43 : $transformer.hashCode());
return result;
}
}
/**
* A prepared version of a default method registry.
*/
protected static class Prepared implements MethodRegistry.Prepared {
/**
* A map of all method descriptions mapped to their handling entries.
*/
private final LinkedHashMap<MethodDescription, Entry> implementations;
/**
* The loaded type initializer of the instrumented type.
*/
private final LoadedTypeInitializer loadedTypeInitializer;
/**
* The type initializer of the instrumented type.
*/
private final TypeInitializer typeInitializer;
/**
* The instrumented type.
*/
private final TypeDescription instrumentedType;
/**
* A method graph describing the instrumented type.
*/
private final MethodGraph.Linked methodGraph;
/**
* The declared or virtually inherited methods of this type.
*/
private final MethodList<?> methods;
/**
* Creates a prepared version of a default method registry.
*
* @param implementations A map of all method descriptions mapped to their handling entries.
* @param loadedTypeInitializer The loaded type initializer of the instrumented type.
* @param typeInitializer The type initializer of the instrumented type.
* @param instrumentedType The instrumented type.
* @param methodGraph A method graph describing the instrumented type.
* @param methods The declared or virtually inherited methods of this type.
*/
protected Prepared(LinkedHashMap<MethodDescription, Entry> implementations, LoadedTypeInitializer loadedTypeInitializer, TypeInitializer typeInitializer, TypeDescription instrumentedType, MethodGraph.Linked methodGraph, MethodList<?> methods) {
this.implementations = implementations;
this.loadedTypeInitializer = loadedTypeInitializer;
this.typeInitializer = typeInitializer;
this.instrumentedType = instrumentedType;
this.methodGraph = methodGraph;
this.methods = methods;
}
@Override
public TypeDescription getInstrumentedType() {
return instrumentedType;
}
@Override
public LoadedTypeInitializer getLoadedTypeInitializer() {
return loadedTypeInitializer;
}
@Override
public TypeInitializer getTypeInitializer() {
return typeInitializer;
}
@Override
public MethodList<?> getMethods() {
return methods;
}
@Override
public MethodList<?> getInstrumentedMethods() {
return new MethodList.Explicit<MethodDescription>(new ArrayList<MethodDescription>(implementations.keySet())).filter(ElementMatchers.not(ElementMatchers.isTypeInitializer()));
}
@Override
public MethodRegistry.Compiled compile(Implementation.Target.Factory implementationTargetFactory, ClassFileVersion classFileVersion) {
Map<Handler, Handler.Compiled> compilationCache = new HashMap<Handler, Handler.Compiled>();
Map<MethodAttributeAppender.Factory, MethodAttributeAppender> attributeAppenderCache = new HashMap<MethodAttributeAppender.Factory, MethodAttributeAppender>();
LinkedHashMap<MethodDescription, Compiled.Entry> entries = new LinkedHashMap<MethodDescription, Compiled.Entry>();
Implementation.Target implementationTarget = implementationTargetFactory.make(instrumentedType, methodGraph, classFileVersion);
for (Map.Entry<MethodDescription, Entry> entry : implementations.entrySet()) {
Handler.Compiled cachedHandler = compilationCache.get(entry.getValue().getHandler());
if (cachedHandler == null) {
cachedHandler = entry.getValue().getHandler().compile(implementationTarget);
compilationCache.put(entry.getValue().getHandler(), cachedHandler);
}
MethodAttributeAppender cachedAttributeAppender = attributeAppenderCache.get(entry.getValue().getAppenderFactory());
if (cachedAttributeAppender == null) {
cachedAttributeAppender = entry.getValue().getAppenderFactory().make(instrumentedType);
attributeAppenderCache.put(entry.getValue().getAppenderFactory(), cachedAttributeAppender);
}
entries.put(entry.getKey(), new Compiled.Entry(cachedHandler, cachedAttributeAppender, entry.getValue().getMethodDescription(), entry.getValue().resolveBridgeTypes(), entry.getValue().getVisibility(), entry.getValue().isBridgeMethod()));
}
return new Compiled(instrumentedType, loadedTypeInitializer, typeInitializer, methods, entries, classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5));
}
/**
* An entry of a prepared method registry.
*/
protected static class Entry {
/**
* The handler for implementing methods.
*/
private final Handler handler;
/**
* A attribute appender factory for appending attributes for any implemented method.
*/
private final MethodAttributeAppender.Factory attributeAppenderFactory;
/**
* The method this entry represents.
*/
private final MethodDescription methodDescription;
/**
* The method's type tokens.
*/
private final Set<MethodDescription.TypeToken> typeTokens;
/**
* The minimum required visibility of this method.
*/
private Visibility visibility;
/**
* Is {@code true} if this entry represents a bridge method.
*/
private final boolean bridgeMethod;
/**
* Creates a new prepared entry.
*
* @param handler The handler for implementing methods.
* @param attributeAppenderFactory A attribute appender factory for appending attributes for any implemented method.
* @param methodDescription The method this entry represents.
* @param typeTokens A set of bridges representing the bridge methods of this method.
* @param visibility The minimum required visibility of this method.
* @param bridgeMethod {@code true} if this entry represents a bridge method.
*/
protected Entry(Handler handler, MethodAttributeAppender.Factory attributeAppenderFactory, MethodDescription methodDescription, Set<MethodDescription.TypeToken> typeTokens, Visibility visibility, boolean bridgeMethod) {
this.handler = handler;
this.attributeAppenderFactory = attributeAppenderFactory;
this.methodDescription = methodDescription;
this.typeTokens = typeTokens;
this.visibility = visibility;
this.bridgeMethod = bridgeMethod;
}
/**
* Creates an entry for a visibility bridge.
*
* @param bridgeTarget The bridge method's target.
* @param visibility The represented method's minimum visibility.
* @return An entry representing a visibility bridge.
*/
protected static Entry forVisibilityBridge(MethodDescription bridgeTarget, Visibility visibility) {
return new Entry(Handler.ForVisibilityBridge.INSTANCE, MethodAttributeAppender.Explicit.of(bridgeTarget), bridgeTarget, Collections.<MethodDescription.TypeToken>emptySet(), visibility, true);
}
/**
* Returns this entry's handler.
*
* @return The entry's handler.
*/
protected Handler getHandler() {
return handler;
}
/**
* Returns this entry's attribute appender factory.
*
* @return This entry's attribute appender factory.
*/
protected MethodAttributeAppender.Factory getAppenderFactory() {
return attributeAppenderFactory;
}
/**
* Returns the method description this entry represents.
*
* @return The method description this entry represents.
*/
protected MethodDescription getMethodDescription() {
return methodDescription;
}
/**
* Resolves the type tokens of all bridge methods that are required to be implemented for this entry.
*
* @return A set of type tokens representing the bridge methods required for implementing this type.
*/
protected Set<MethodDescription.TypeToken> resolveBridgeTypes() {
HashSet<MethodDescription.TypeToken> typeTokens = new HashSet<MethodDescription.TypeToken>(this.typeTokens);
typeTokens.remove(methodDescription.asTypeToken());
return typeTokens;
}
/**
* Returns the represented method's minimum visibility.
*
* @return The represented method's minimum visibility.
*/
protected Visibility getVisibility() {
return visibility;
}
/**
* Returns {@code true} if this entry represents a bridge method.
*
* @return {@code true} if this entry represents a bridge method.
*/
protected boolean isBridgeMethod() {
return bridgeMethod;
}
@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 MethodRegistry.Default.Prepared.Entry)) return false;
final MethodRegistry.Default.Prepared.Entry other = (MethodRegistry.Default.Prepared.Entry) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$handler = this.getHandler();
final java.lang.Object other$handler = other.getHandler();
if (this$handler == null ? other$handler != null : !this$handler.equals(other$handler)) return false;
final java.lang.Object this$attributeAppenderFactory = this.attributeAppenderFactory;
final java.lang.Object other$attributeAppenderFactory = other.attributeAppenderFactory;
if (this$attributeAppenderFactory == null ? other$attributeAppenderFactory != null : !this$attributeAppenderFactory.equals(other$attributeAppenderFactory)) return false;
final java.lang.Object this$methodDescription = this.getMethodDescription();
final java.lang.Object other$methodDescription = other.getMethodDescription();
if (this$methodDescription == null ? other$methodDescription != null : !this$methodDescription.equals(other$methodDescription)) return false;
final java.lang.Object this$typeTokens = this.typeTokens;
final java.lang.Object other$typeTokens = other.typeTokens;
if (this$typeTokens == null ? other$typeTokens != null : !this$typeTokens.equals(other$typeTokens)) return false;
final java.lang.Object this$visibility = this.getVisibility();
final java.lang.Object other$visibility = other.getVisibility();
if (this$visibility == null ? other$visibility != null : !this$visibility.equals(other$visibility)) return false;
if (this.isBridgeMethod() != other.isBridgeMethod()) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Default.Prepared.Entry;
}
@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 $handler = this.getHandler();
result = result * PRIME + ($handler == null ? 43 : $handler.hashCode());
final java.lang.Object $attributeAppenderFactory = this.attributeAppenderFactory;
result = result * PRIME + ($attributeAppenderFactory == null ? 43 : $attributeAppenderFactory.hashCode());
final java.lang.Object $methodDescription = this.getMethodDescription();
result = result * PRIME + ($methodDescription == null ? 43 : $methodDescription.hashCode());
final java.lang.Object $typeTokens = this.typeTokens;
result = result * PRIME + ($typeTokens == null ? 43 : $typeTokens.hashCode());
final java.lang.Object $visibility = this.getVisibility();
result = result * PRIME + ($visibility == null ? 43 : $visibility.hashCode());
result = result * PRIME + (this.isBridgeMethod() ? 79 : 97);
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 MethodRegistry.Default.Prepared)) return false;
final MethodRegistry.Default.Prepared other = (MethodRegistry.Default.Prepared) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$implementations = this.implementations;
final java.lang.Object other$implementations = other.implementations;
if (this$implementations == null ? other$implementations != null : !this$implementations.equals(other$implementations)) return false;
final java.lang.Object this$loadedTypeInitializer = this.getLoadedTypeInitializer();
final java.lang.Object other$loadedTypeInitializer = other.getLoadedTypeInitializer();
if (this$loadedTypeInitializer == null ? other$loadedTypeInitializer != null : !this$loadedTypeInitializer.equals(other$loadedTypeInitializer)) return false;
final java.lang.Object this$typeInitializer = this.getTypeInitializer();
final java.lang.Object other$typeInitializer = other.getTypeInitializer();
if (this$typeInitializer == null ? other$typeInitializer != null : !this$typeInitializer.equals(other$typeInitializer)) return false;
final java.lang.Object this$instrumentedType = this.getInstrumentedType();
final java.lang.Object other$instrumentedType = other.getInstrumentedType();
if (this$instrumentedType == null ? other$instrumentedType != null : !this$instrumentedType.equals(other$instrumentedType)) return false;
final java.lang.Object this$methodGraph = this.methodGraph;
final java.lang.Object other$methodGraph = other.methodGraph;
if (this$methodGraph == null ? other$methodGraph != null : !this$methodGraph.equals(other$methodGraph)) return false;
final java.lang.Object this$methods = this.getMethods();
final java.lang.Object other$methods = other.getMethods();
if (this$methods == null ? other$methods != null : !this$methods.equals(other$methods)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Default.Prepared;
}
@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 $implementations = this.implementations;
result = result * PRIME + ($implementations == null ? 43 : $implementations.hashCode());
final java.lang.Object $loadedTypeInitializer = this.getLoadedTypeInitializer();
result = result * PRIME + ($loadedTypeInitializer == null ? 43 : $loadedTypeInitializer.hashCode());
final java.lang.Object $typeInitializer = this.getTypeInitializer();
result = result * PRIME + ($typeInitializer == null ? 43 : $typeInitializer.hashCode());
final java.lang.Object $instrumentedType = this.getInstrumentedType();
result = result * PRIME + ($instrumentedType == null ? 43 : $instrumentedType.hashCode());
final java.lang.Object $methodGraph = this.methodGraph;
result = result * PRIME + ($methodGraph == null ? 43 : $methodGraph.hashCode());
final java.lang.Object $methods = this.getMethods();
result = result * PRIME + ($methods == null ? 43 : $methods.hashCode());
return result;
}
}
/**
* A compiled version of a default method registry.
*/
protected static class Compiled implements MethodRegistry.Compiled {
/**
* The instrumented type.
*/
private final TypeDescription instrumentedType;
/**
* The loaded type initializer of the instrumented type.
*/
private final LoadedTypeInitializer loadedTypeInitializer;
/**
* The type initializer of the instrumented type.
*/
private final TypeInitializer typeInitializer;
/**
* The declared or virtually inherited methods of this type.
*/
private final MethodList<?> methods;
/**
* A map of all method descriptions mapped to their handling entries.
*/
private final LinkedHashMap<MethodDescription, Entry> implementations;
/**
* {@code true} if the created type supports bridge methods.
*/
private final boolean supportsBridges;
/**
* Creates a new compiled version of a default method registry.
*
* @param instrumentedType The instrumented type.
* @param loadedTypeInitializer The loaded type initializer of the instrumented type.
* @param typeInitializer The type initializer of the instrumented type.
* @param methods The declared or virtually inherited methods of this type.
* @param implementations A map of all method descriptions mapped to their handling entries.
* @param supportsBridges {@code true} if the created type supports bridge methods.
*/
protected Compiled(TypeDescription instrumentedType, LoadedTypeInitializer loadedTypeInitializer, TypeInitializer typeInitializer, MethodList<?> methods, LinkedHashMap<MethodDescription, Entry> implementations, boolean supportsBridges) {
this.instrumentedType = instrumentedType;
this.loadedTypeInitializer = loadedTypeInitializer;
this.typeInitializer = typeInitializer;
this.methods = methods;
this.implementations = implementations;
this.supportsBridges = supportsBridges;
}
@Override
public TypeDescription getInstrumentedType() {
return instrumentedType;
}
@Override
public LoadedTypeInitializer getLoadedTypeInitializer() {
return loadedTypeInitializer;
}
@Override
public TypeInitializer getTypeInitializer() {
return typeInitializer;
}
@Override
public MethodList<?> getMethods() {
return methods;
}
@Override
public MethodList<?> getInstrumentedMethods() {
return new MethodList.Explicit<MethodDescription>(new ArrayList<MethodDescription>(implementations.keySet())).filter(ElementMatchers.not(ElementMatchers.isTypeInitializer()));
}
@Override
public Record target(MethodDescription methodDescription) {
Entry entry = implementations.get(methodDescription);
return entry == null ? new Record.ForNonImplementedMethod(methodDescription) : entry.bind(instrumentedType, supportsBridges);
}
/**
* An entry of a compiled method registry.
*/
protected static class Entry {
/**
* The handler to be used for implementing a method.
*/
private final Handler.Compiled handler;
/**
* The attribute appender of a compiled method.
*/
private final MethodAttributeAppender attributeAppender;
/**
* The method to be implemented including potential transformations.
*/
private final MethodDescription methodDescription;
/**
* The type tokens representing all bridge methods for the method.
*/
private final Set<MethodDescription.TypeToken> bridgeTypes;
/**
* The represented method's minimum visibility.
*/
private final Visibility visibility;
/**
* {@code true} if this entry represents a bridge method.
*/
private final boolean bridgeMethod;
/**
* Creates a new entry for a compiled method registry.
*
* @param handler The handler to be used for implementing a method.
* @param attributeAppender The attribute appender of a compiled method.
* @param methodDescription The method to be implemented including potential transformations.
* @param bridgeTypes The type tokens representing all bridge methods for the method.
* @param visibility The represented method's minimum visibility.
* @param bridgeMethod {@code true} if this entry represents a bridge method.
*/
protected Entry(Handler.Compiled handler, MethodAttributeAppender attributeAppender, MethodDescription methodDescription, Set<MethodDescription.TypeToken> bridgeTypes, Visibility visibility, boolean bridgeMethod) {
this.handler = handler;
this.attributeAppender = attributeAppender;
this.methodDescription = methodDescription;
this.bridgeTypes = bridgeTypes;
this.visibility = visibility;
this.bridgeMethod = bridgeMethod;
}
/**
* Transforms this entry into a method record.
*
* @param instrumentedType The instrumented type to bind.
* @param supportsBridges {@code true} if the record should support bridge methods.
* @return A record representing this entry's properties.
*/
protected Record bind(TypeDescription instrumentedType, boolean supportsBridges) {
if (bridgeMethod && !supportsBridges) {
return new Record.ForNonImplementedMethod(methodDescription);
}
Record record = handler.assemble(methodDescription, attributeAppender, visibility);
return supportsBridges ? TypeWriter.MethodPool.Record.AccessBridgeWrapper.of(record, instrumentedType, methodDescription, bridgeTypes, attributeAppender) : record;
}
@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 MethodRegistry.Default.Compiled.Entry)) return false;
final MethodRegistry.Default.Compiled.Entry other = (MethodRegistry.Default.Compiled.Entry) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$handler = this.handler;
final java.lang.Object other$handler = other.handler;
if (this$handler == null ? other$handler != null : !this$handler.equals(other$handler)) return false;
final java.lang.Object this$attributeAppender = this.attributeAppender;
final java.lang.Object other$attributeAppender = other.attributeAppender;
if (this$attributeAppender == null ? other$attributeAppender != null : !this$attributeAppender.equals(other$attributeAppender)) return false;
final java.lang.Object this$methodDescription = this.methodDescription;
final java.lang.Object other$methodDescription = other.methodDescription;
if (this$methodDescription == null ? other$methodDescription != null : !this$methodDescription.equals(other$methodDescription)) return false;
final java.lang.Object this$bridgeTypes = this.bridgeTypes;
final java.lang.Object other$bridgeTypes = other.bridgeTypes;
if (this$bridgeTypes == null ? other$bridgeTypes != null : !this$bridgeTypes.equals(other$bridgeTypes)) return false;
final java.lang.Object this$visibility = this.visibility;
final java.lang.Object other$visibility = other.visibility;
if (this$visibility == null ? other$visibility != null : !this$visibility.equals(other$visibility)) return false;
if (this.bridgeMethod != other.bridgeMethod) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Default.Compiled.Entry;
}
@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 $handler = this.handler;
result = result * PRIME + ($handler == null ? 43 : $handler.hashCode());
final java.lang.Object $attributeAppender = this.attributeAppender;
result = result * PRIME + ($attributeAppender == null ? 43 : $attributeAppender.hashCode());
final java.lang.Object $methodDescription = this.methodDescription;
result = result * PRIME + ($methodDescription == null ? 43 : $methodDescription.hashCode());
final java.lang.Object $bridgeTypes = this.bridgeTypes;
result = result * PRIME + ($bridgeTypes == null ? 43 : $bridgeTypes.hashCode());
final java.lang.Object $visibility = this.visibility;
result = result * PRIME + ($visibility == null ? 43 : $visibility.hashCode());
result = result * PRIME + (this.bridgeMethod ? 79 : 97);
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 MethodRegistry.Default.Compiled)) return false;
final MethodRegistry.Default.Compiled other = (MethodRegistry.Default.Compiled) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$instrumentedType = this.getInstrumentedType();
final java.lang.Object other$instrumentedType = other.getInstrumentedType();
if (this$instrumentedType == null ? other$instrumentedType != null : !this$instrumentedType.equals(other$instrumentedType)) return false;
final java.lang.Object this$loadedTypeInitializer = this.getLoadedTypeInitializer();
final java.lang.Object other$loadedTypeInitializer = other.getLoadedTypeInitializer();
if (this$loadedTypeInitializer == null ? other$loadedTypeInitializer != null : !this$loadedTypeInitializer.equals(other$loadedTypeInitializer)) return false;
final java.lang.Object this$typeInitializer = this.getTypeInitializer();
final java.lang.Object other$typeInitializer = other.getTypeInitializer();
if (this$typeInitializer == null ? other$typeInitializer != null : !this$typeInitializer.equals(other$typeInitializer)) return false;
final java.lang.Object this$methods = this.getMethods();
final java.lang.Object other$methods = other.getMethods();
if (this$methods == null ? other$methods != null : !this$methods.equals(other$methods)) return false;
final java.lang.Object this$implementations = this.implementations;
final java.lang.Object other$implementations = other.implementations;
if (this$implementations == null ? other$implementations != null : !this$implementations.equals(other$implementations)) return false;
if (this.supportsBridges != other.supportsBridges) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Default.Compiled;
}
@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.getInstrumentedType();
result = result * PRIME + ($instrumentedType == null ? 43 : $instrumentedType.hashCode());
final java.lang.Object $loadedTypeInitializer = this.getLoadedTypeInitializer();
result = result * PRIME + ($loadedTypeInitializer == null ? 43 : $loadedTypeInitializer.hashCode());
final java.lang.Object $typeInitializer = this.getTypeInitializer();
result = result * PRIME + ($typeInitializer == null ? 43 : $typeInitializer.hashCode());
final java.lang.Object $methods = this.getMethods();
result = result * PRIME + ($methods == null ? 43 : $methods.hashCode());
final java.lang.Object $implementations = this.implementations;
result = result * PRIME + ($implementations == null ? 43 : $implementations.hashCode());
result = result * PRIME + (this.supportsBridges ? 79 : 97);
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 MethodRegistry.Default)) return false;
final MethodRegistry.Default other = (MethodRegistry.Default) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$entries = this.entries;
final java.lang.Object other$entries = other.entries;
if (this$entries == null ? other$entries != null : !this$entries.equals(other$entries)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRegistry.Default;
}
@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 $entries = this.entries;
result = result * PRIME + ($entries == null ? 43 : $entries.hashCode());
return result;
}
}
}