// Generated by delombok at Sun Feb 26 12:31:38 KST 2017
package scouter.bytebuddy.dynamic.scaffold.inline;
import scouter.bytebuddy.ClassFileVersion;
import scouter.bytebuddy.description.annotation.AnnotationList;
import scouter.bytebuddy.description.annotation.AnnotationValue;
import scouter.bytebuddy.description.method.MethodDescription;
import scouter.bytebuddy.description.method.ParameterDescription;
import scouter.bytebuddy.description.method.ParameterList;
import scouter.bytebuddy.description.type.TypeDescription;
import scouter.bytebuddy.description.type.TypeList;
import scouter.bytebuddy.dynamic.DynamicType;
import scouter.bytebuddy.implementation.MethodAccessorFactory;
import scouter.bytebuddy.implementation.auxiliary.AuxiliaryType;
import scouter.bytebuddy.implementation.auxiliary.TrivialType;
import scouter.bytebuddy.implementation.bytecode.StackManipulation;
import scouter.bytebuddy.implementation.bytecode.constant.NullConstant;
import scouter.bytebuddy.utility.CompoundList;
import scouter.bytebuddy.jar.asm.Opcodes;
import java.util.*;
import static scouter.bytebuddy.matcher.ElementMatchers.is;
/**
* A method rebase resolver is responsible for mapping methods of an instrumented type to an alternative signature.
* This way a method can exist in two versions within a class:
* <ol>
* <li>The rebased method which represents the original implementation as it is present in a class file.</li>
* <li>An overriden method which implements user code which is still able to invoke the original, rebased method.</li>
* </ol>
*/
public interface MethodRebaseResolver {
/**
* Checks if a method is eligible for rebasing and resolves this possibly rebased method.
*
* @param methodDescription A description of the method to resolve.
* @return A resolution for the given method.
*/
Resolution resolve(MethodDescription.InDefinedShape methodDescription);
/**
* Returns a (potentially empty) list of auxiliary types that are required by this method rebase resolver.
*
* @return A list of auxiliary types that are required by this method rebase resolver.
*/
List<DynamicType> getAuxiliaryTypes();
/**
* Returns a map of all rebasable methods' signature tokens to their resolution.
*
* @return A map of all rebasable methods' signature tokens to their resolution.
*/
Map<MethodDescription.SignatureToken, Resolution> asTokenMap();
/**
* A method rebase resolver that preserves any method in its original form.
*/
enum Disabled implements MethodRebaseResolver {
/**
* The singleton instance.
*/
INSTANCE;
@Override
public Resolution resolve(MethodDescription.InDefinedShape methodDescription) {
return new Resolution.Preserved(methodDescription);
}
@Override
public List<DynamicType> getAuxiliaryTypes() {
return Collections.emptyList();
}
@Override
public Map<MethodDescription.SignatureToken, Resolution> asTokenMap() {
return Collections.emptyMap();
}
}
/**
* A resolution for a method that was checked by a {@link MethodRebaseResolver}.
*/
interface Resolution {
/**
* Checks if this resolution represents a rebased method.
*
* @return {@code true} if this resolution requires to rebase a method.
*/
boolean isRebased();
/**
* Returns the resolved method if this resolution represents a rebased method or the original method.
*
* @return The resolved method if this resolution represents a rebased method or the original method.
*/
MethodDescription.InDefinedShape getResolvedMethod();
/**
* A rebased method might require additional arguments in order to create a distinct signature. The
* stack manipulation that is returned from this method loads these arguments onto the operand stack. For
* a non-rebased method, this method throws an {@link java.lang.IllegalArgumentException}.
*
* @return A stack manipulation that loaded the additional arguments onto the stack, if any.
*/
StackManipulation getAdditionalArguments();
/**
* A {@link MethodRebaseResolver.Resolution} of a non-rebased method.
*/
class Preserved implements Resolution {
/**
* The preserved method.
*/
private final MethodDescription.InDefinedShape methodDescription;
/**
* Creates a new {@link MethodRebaseResolver.Resolution} for
* a non-rebased method.
*
* @param methodDescription The preserved method.
*/
public Preserved(MethodDescription.InDefinedShape methodDescription) {
this.methodDescription = methodDescription;
}
@Override
public boolean isRebased() {
return false;
}
@Override
public MethodDescription.InDefinedShape getResolvedMethod() {
return methodDescription;
}
@Override
public StackManipulation getAdditionalArguments() {
throw new IllegalStateException("Cannot process additional arguments for non-rebased method: " + methodDescription);
}
@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 MethodRebaseResolver.Resolution.Preserved)) return false;
final MethodRebaseResolver.Resolution.Preserved other = (MethodRebaseResolver.Resolution.Preserved) o;
if (!other.canEqual((java.lang.Object) this)) 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;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRebaseResolver.Resolution.Preserved;
}
@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 $methodDescription = this.methodDescription;
result = result * PRIME + ($methodDescription == null ? 43 : $methodDescription.hashCode());
return result;
}
}
/**
* A {@link MethodRebaseResolver.Resolution} of a rebased method.
*/
class ForRebasedMethod implements Resolution {
/**
* The rebased method.
*/
private final MethodDescription.InDefinedShape methodDescription;
/**
* Creates a resolution for a rebased method.
*
* @param methodDescription The rebased method.
*/
protected ForRebasedMethod(MethodDescription.InDefinedShape methodDescription) {
this.methodDescription = methodDescription;
}
/**
* Resolves a rebasement for the provided method.
*
* @param instrumentedType The instrumented type.
* @param methodDescription The method to be rebased.
* @param methodNameTransformer The transformer to use for renaming the method.
* @return A resolution for rebasing the provided method.
*/
public static Resolution of(TypeDescription instrumentedType, MethodDescription.InDefinedShape methodDescription, MethodNameTransformer methodNameTransformer) {
return new ForRebasedMethod(new RebasedMethod(instrumentedType, methodDescription, methodNameTransformer));
}
@Override
public boolean isRebased() {
return true;
}
@Override
public MethodDescription.InDefinedShape getResolvedMethod() {
return methodDescription;
}
@Override
public StackManipulation getAdditionalArguments() {
return StackManipulation.Trivial.INSTANCE;
}
/**
* A description of a rebased method.
*/
protected static class RebasedMethod extends MethodDescription.InDefinedShape.AbstractBase {
/**
* The instrumented type.
*/
private final TypeDescription instrumentedType;
/**
* The method that is being rebased.
*/
private final InDefinedShape methodDescription;
/**
* The transformer to use for renaming the method.
*/
private final MethodNameTransformer methodNameTransformer;
/**
* Creates a new rebased method.
*
* @param instrumentedType The instrumented type.
* @param methodDescription The method that is being rebased.
* @param methodNameTransformer The transformer to use for renaming the method.
*/
protected RebasedMethod(TypeDescription instrumentedType, InDefinedShape methodDescription, MethodNameTransformer methodNameTransformer) {
this.instrumentedType = instrumentedType;
this.methodDescription = methodDescription;
this.methodNameTransformer = methodNameTransformer;
}
@Override
public TypeDescription.Generic getReturnType() {
return methodDescription.getReturnType().asRawType();
}
@Override
public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
return new ParameterList.Explicit.ForTypes(this, methodDescription.getParameters().asTypeList().asRawTypes());
}
@Override
public TypeList.Generic getExceptionTypes() {
return methodDescription.getExceptionTypes().asRawTypes();
}
@Override
public AnnotationValue<?, ?> getDefaultValue() {
return AnnotationValue.UNDEFINED;
}
@Override
public TypeList.Generic getTypeVariables() {
return new TypeList.Generic.Empty();
}
@Override
public AnnotationList getDeclaredAnnotations() {
return new AnnotationList.Empty();
}
@Override
public TypeDescription getDeclaringType() {
return methodDescription.getDeclaringType();
}
@Override
public int getModifiers() {
return Opcodes.ACC_SYNTHETIC | (methodDescription.isStatic() ? Opcodes.ACC_STATIC : EMPTY_MASK) | (methodDescription.isNative() ? Opcodes.ACC_NATIVE : EMPTY_MASK) | (instrumentedType.isInterface() ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PRIVATE);
}
@Override
public String getInternalName() {
return methodNameTransformer.transform(methodDescription);
}
}
@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 MethodRebaseResolver.Resolution.ForRebasedMethod)) return false;
final MethodRebaseResolver.Resolution.ForRebasedMethod other = (MethodRebaseResolver.Resolution.ForRebasedMethod) o;
if (!other.canEqual((java.lang.Object) this)) 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;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRebaseResolver.Resolution.ForRebasedMethod;
}
@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 $methodDescription = this.methodDescription;
result = result * PRIME + ($methodDescription == null ? 43 : $methodDescription.hashCode());
return result;
}
}
/**
* A {@link MethodRebaseResolver.Resolution} of a rebased constructor.
*/
class ForRebasedConstructor implements Resolution {
/**
* The rebased constructor.
*/
private final MethodDescription.InDefinedShape methodDescription;
/**
* Creates a new resolution for a rebased constructor.
*
* @param methodDescription The rebased constructor.
*/
protected ForRebasedConstructor(MethodDescription.InDefinedShape methodDescription) {
this.methodDescription = methodDescription;
}
/**
* Resolves a constructor rebasement.
*
* @param methodDescription The constructor to rebase.
* @param placeholderType The placeholder type to use to distinguish the constructor's signature.
* @return A resolution of the provided constructor.
*/
public static Resolution of(MethodDescription.InDefinedShape methodDescription, TypeDescription placeholderType) {
return new ForRebasedConstructor(new RebasedConstructor(methodDescription, placeholderType));
}
@Override
public boolean isRebased() {
return true;
}
@Override
public MethodDescription.InDefinedShape getResolvedMethod() {
return methodDescription;
}
@Override
public StackManipulation getAdditionalArguments() {
return NullConstant.INSTANCE;
}
/**
* An description of a rebased constructor.
*/
protected static class RebasedConstructor extends MethodDescription.InDefinedShape.AbstractBase {
/**
* The constructor that is rebased.
*/
private final InDefinedShape methodDescription;
/**
* The placeholder type that is used to distinguish the constructor's signature.
*/
private final TypeDescription placeholderType;
/**
* Creates a new rebased constructor.
*
* @param methodDescription The constructor that is rebased.
* @param placeholderType The placeholder type that is used to distinguish the constructor's signature.
*/
protected RebasedConstructor(InDefinedShape methodDescription, TypeDescription placeholderType) {
this.methodDescription = methodDescription;
this.placeholderType = placeholderType;
}
@Override
public TypeDescription.Generic getReturnType() {
return TypeDescription.Generic.VOID;
}
@Override
public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
return new ParameterList.Explicit.ForTypes(this, CompoundList.of(methodDescription.getParameters().asTypeList().asErasures(), placeholderType));
}
@Override
public TypeList.Generic getExceptionTypes() {
return methodDescription.getExceptionTypes().asRawTypes();
}
@Override
public AnnotationValue<?, ?> getDefaultValue() {
return AnnotationValue.UNDEFINED;
}
@Override
public TypeList.Generic getTypeVariables() {
return new TypeList.Generic.Empty();
}
@Override
public AnnotationList getDeclaredAnnotations() {
return new AnnotationList.Empty();
}
@Override
public TypeDescription getDeclaringType() {
return methodDescription.getDeclaringType();
}
@Override
public int getModifiers() {
return Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PRIVATE;
}
@Override
public String getInternalName() {
return MethodDescription.CONSTRUCTOR_INTERNAL_NAME;
}
}
@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 MethodRebaseResolver.Resolution.ForRebasedConstructor)) return false;
final MethodRebaseResolver.Resolution.ForRebasedConstructor other = (MethodRebaseResolver.Resolution.ForRebasedConstructor) o;
if (!other.canEqual((java.lang.Object) this)) 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;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRebaseResolver.Resolution.ForRebasedConstructor;
}
@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 $methodDescription = this.methodDescription;
result = result * PRIME + ($methodDescription == null ? 43 : $methodDescription.hashCode());
return result;
}
}
}
/**
* A default implementation of a method rebase resolver.
*/
class Default implements MethodRebaseResolver {
/**
* A mapping of rebased methods to their existing resolutions.
*/
private final Map<MethodDescription.InDefinedShape, Resolution> resolutions;
/**
* A list of dynamic types that need to be appended to the created type in order to allow for the rebasement.
*/
private final List<DynamicType> dynamicTypes;
/**
* Creates a new default method rebased resolver.
*
* @param resolutions A mapping of rebased methods to their existing resolutions.
* @param dynamicTypes A list of dynamic types that need to be appended to the created type in order to allow for the rebasement.
*/
protected Default(Map<MethodDescription.InDefinedShape, Resolution> resolutions, List<DynamicType> dynamicTypes) {
this.resolutions = resolutions;
this.dynamicTypes = dynamicTypes;
}
/**
* Creates a new method rebase resolver.
*
* @param instrumentedType The instrumented type.
* @param rebaseableMethodTokens Tokens describing all methods that can possibly be rebased.
* @param classFileVersion The class file version for the instrumentation.
* @param auxiliaryTypeNamingStrategy The naming strategy for naming a potential auxiliary type.
* @param methodNameTransformer A transformer for method names.
* @return A method rebase resolver that is capable of rebasing any of the provided methods.
*/
public static MethodRebaseResolver make(TypeDescription instrumentedType, Set<? extends MethodDescription.Token> rebaseableMethodTokens, ClassFileVersion classFileVersion, AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy, MethodNameTransformer methodNameTransformer) {
DynamicType placeholderType = null;
Map<MethodDescription.InDefinedShape, Resolution> resolutions = new HashMap<MethodDescription.InDefinedShape, Resolution>();
for (MethodDescription.InDefinedShape instrumentedMethod : instrumentedType.getDeclaredMethods()) {
if (rebaseableMethodTokens.contains(instrumentedMethod.asToken(is(instrumentedType)))) {
Resolution resolution;
if (instrumentedMethod.isConstructor()) {
if (placeholderType == null) {
placeholderType = TrivialType.SIGNATURE_RELEVANT.make(auxiliaryTypeNamingStrategy.name(instrumentedType), classFileVersion, MethodAccessorFactory.Illegal.INSTANCE);
}
resolution = Resolution.ForRebasedConstructor.of(instrumentedMethod, placeholderType.getTypeDescription());
} else {
resolution = Resolution.ForRebasedMethod.of(instrumentedType, instrumentedMethod, methodNameTransformer);
}
resolutions.put(instrumentedMethod, resolution);
}
}
return placeholderType == null ? new Default(resolutions, Collections.<DynamicType>emptyList()) : new Default(resolutions, Collections.singletonList(placeholderType));
}
@Override
public Resolution resolve(MethodDescription.InDefinedShape methodDescription) {
Resolution resolution = resolutions.get(methodDescription);
return resolution == null ? new Resolution.Preserved(methodDescription) : resolution;
}
@Override
public List<DynamicType> getAuxiliaryTypes() {
return dynamicTypes;
}
@Override
public Map<MethodDescription.SignatureToken, Resolution> asTokenMap() {
Map<MethodDescription.SignatureToken, Resolution> tokenMap = new HashMap<MethodDescription.SignatureToken, Resolution>();
for (Map.Entry<MethodDescription.InDefinedShape, Resolution> entry : resolutions.entrySet()) {
tokenMap.put(entry.getKey().asSignatureToken(), entry.getValue());
}
return tokenMap;
}
@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 MethodRebaseResolver.Default)) return false;
final MethodRebaseResolver.Default other = (MethodRebaseResolver.Default) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$resolutions = this.resolutions;
final java.lang.Object other$resolutions = other.resolutions;
if (this$resolutions == null ? other$resolutions != null : !this$resolutions.equals(other$resolutions)) return false;
final java.lang.Object this$dynamicTypes = this.dynamicTypes;
final java.lang.Object other$dynamicTypes = other.dynamicTypes;
if (this$dynamicTypes == null ? other$dynamicTypes != null : !this$dynamicTypes.equals(other$dynamicTypes)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof MethodRebaseResolver.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 $resolutions = this.resolutions;
result = result * PRIME + ($resolutions == null ? 43 : $resolutions.hashCode());
final java.lang.Object $dynamicTypes = this.dynamicTypes;
result = result * PRIME + ($dynamicTypes == null ? 43 : $dynamicTypes.hashCode());
return result;
}
}
}