From 17a0b4d0172c0b3399fb5ed0ef1f89b41a1fc67f Mon Sep 17 00:00:00 2001 From: zaaarf Date: Tue, 21 Mar 2023 18:46:23 +0100 Subject: chore: reorganize, add ProxyType enum --- src/main/java/ftbsc/lll/proxies/AbstractProxy.java | 12 +- src/main/java/ftbsc/lll/proxies/FieldProxy.java | 95 ---------- src/main/java/ftbsc/lll/proxies/MethodProxy.java | 185 ------------------- src/main/java/ftbsc/lll/proxies/PackageProxy.java | 51 ------ src/main/java/ftbsc/lll/proxies/ProxyType.java | 11 ++ .../java/ftbsc/lll/proxies/QualifiableProxy.java | 11 +- src/main/java/ftbsc/lll/proxies/TypeProxy.java | 196 -------------------- .../java/ftbsc/lll/proxies/impl/FieldProxy.java | 98 ++++++++++ .../java/ftbsc/lll/proxies/impl/MethodProxy.java | 188 +++++++++++++++++++ .../java/ftbsc/lll/proxies/impl/PackageProxy.java | 54 ++++++ .../java/ftbsc/lll/proxies/impl/TypeProxy.java | 199 +++++++++++++++++++++ .../ftbsc/lll/tools/nodes/FieldProxyInsnNode.java | 2 +- .../ftbsc/lll/tools/nodes/MethodProxyInsnNode.java | 2 +- .../ftbsc/lll/tools/nodes/TypeProxyInsnNode.java | 2 +- 14 files changed, 566 insertions(+), 540 deletions(-) delete mode 100644 src/main/java/ftbsc/lll/proxies/FieldProxy.java delete mode 100644 src/main/java/ftbsc/lll/proxies/MethodProxy.java delete mode 100644 src/main/java/ftbsc/lll/proxies/PackageProxy.java create mode 100644 src/main/java/ftbsc/lll/proxies/ProxyType.java delete mode 100644 src/main/java/ftbsc/lll/proxies/TypeProxy.java create mode 100644 src/main/java/ftbsc/lll/proxies/impl/FieldProxy.java create mode 100644 src/main/java/ftbsc/lll/proxies/impl/MethodProxy.java create mode 100644 src/main/java/ftbsc/lll/proxies/impl/PackageProxy.java create mode 100644 src/main/java/ftbsc/lll/proxies/impl/TypeProxy.java (limited to 'src/main/java/ftbsc/lll') diff --git a/src/main/java/ftbsc/lll/proxies/AbstractProxy.java b/src/main/java/ftbsc/lll/proxies/AbstractProxy.java index d60f3d5..054cef9 100644 --- a/src/main/java/ftbsc/lll/proxies/AbstractProxy.java +++ b/src/main/java/ftbsc/lll/proxies/AbstractProxy.java @@ -3,12 +3,16 @@ package ftbsc.lll.proxies; import org.objectweb.asm.Type; /** - * Abstract proxy class, implementing common aspects - * of {@link MethodProxy} and {@link FieldProxy}. + * Abstract proxy class, implementing common aspects. * @since 0.3.0 */ public abstract class AbstractProxy { + /** + * Which type of proxy this is. + */ + public final ProxyType proxyType; + /** * The name of the corresponding element. */ @@ -37,12 +41,14 @@ public abstract class AbstractProxy { * @param descriptor the descriptor for the element * @param modifiers the modifiers, as a packed int * @param parent the FQN of the parent class + * @param proxyType the {@link ProxyType} being represented here */ - protected AbstractProxy(String name, String descriptor, int modifiers, QualifiableProxy parent) { + protected AbstractProxy(String name, String descriptor, int modifiers, QualifiableProxy parent, ProxyType proxyType) { this.name = name; this.descriptor = descriptor; this.modifiers = modifiers; this.parent = parent; + this.proxyType = proxyType; } /** diff --git a/src/main/java/ftbsc/lll/proxies/FieldProxy.java b/src/main/java/ftbsc/lll/proxies/FieldProxy.java deleted file mode 100644 index 8732997..0000000 --- a/src/main/java/ftbsc/lll/proxies/FieldProxy.java +++ /dev/null @@ -1,95 +0,0 @@ -package ftbsc.lll.proxies; - -import org.objectweb.asm.Type; - -import java.lang.reflect.Field; - -/** - * A container for information about class fields to be used - * in ASM patching. - * @since 0.3.0 - */ -public class FieldProxy extends AbstractProxy { - /** - * A public constructor, builds a proxy from a {@link Field} - * obtained from reflection. - * @param f the {@link Field} object corresponding to this. - */ - public FieldProxy(Field f) { - super(f.getName(), Type.getDescriptor(f.getType()), f.getModifiers(), TypeProxy.from(f.getDeclaringClass())); - } - - /** - * Protected constructor, called only from the builder. - * @param name the name of the field - * @param descriptor the descriptor of the field - * @param modifiers the modifiers of the field - * @param parent the {@link QualifiableProxy} for the parent - */ - protected FieldProxy(String name, String descriptor, int modifiers, QualifiableProxy parent) { - super(name, descriptor, modifiers, parent); - } - - /** - * Returns a new instance of {@link FieldProxy.Builder}. - * @param name the name of the field - * @return the builder object for field proxies - */ - public static Builder builder(String name) { - return new Builder(name); - } - - /** - * Indicates whether the given object is a proxy for the same element as this. - * @param obj the object to perform - * @return true if it's equal - */ - @Override - public boolean equals(Object obj) { - return obj instanceof FieldProxy && super.equals(obj); - } - - /** - * A builder object for {@link FieldProxy}. - */ - public static class Builder extends AbstractProxy.Builder { - /** - * The constructor of the builder, used only internally. - * @param name the name of the field - */ - Builder(String name) { - super(name); - } - - /** - * Sets the parent class of this field to the one described by the - * fully qualified name and with the given modifiers. - * @param parentFQN the fully qualified name of the parent - * @param modifiers the modifiers of the parent - * @return the builder's state after the change - */ - public Builder setParent(String parentFQN, int modifiers) { - super.setParent(TypeProxy.from(parentFQN, 0, modifiers)); - return this; - } - - /** - * Sets the parent class of this field to the one described by the - * fully qualified name. - * @param parentFQN the fully qualified name of the parent - * @return the builder's state after the change - */ - public Builder setParent(String parentFQN) { - return this.setParent(parentFQN, 0); - } - - /** - * Builds a {@link FieldProxy} of the given kind. - * @return the built {@link FieldProxy} - */ - @Override - public FieldProxy build() { - return new FieldProxy(this.name, this.descriptor, this.modifiers, this.parent); - } - } -} diff --git a/src/main/java/ftbsc/lll/proxies/MethodProxy.java b/src/main/java/ftbsc/lll/proxies/MethodProxy.java deleted file mode 100644 index c906ec7..0000000 --- a/src/main/java/ftbsc/lll/proxies/MethodProxy.java +++ /dev/null @@ -1,185 +0,0 @@ -package ftbsc.lll.proxies; - -import org.objectweb.asm.Type; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static ftbsc.lll.tools.DescriptorBuilder.nameToDescriptor; - -/** - * A container for information about class methods to be used - * in ASM patching. - * @since 0.3.0 - */ -public class MethodProxy extends AbstractProxy { - - /** - * An array of {@link TypeProxy} each representing the parameters of the method. - */ - public final TypeProxy[] parameters; - - /** - * The {@link TypeProxy} for the return type of the method. - */ - public final TypeProxy returnType; - - /** - * A protected constructor, called only from the builder. - * @param name the name of the method - * @param modifiers the modifiers of the method - * @param parent the {@link QualifiableProxy} for the parent - * @param parameters the parameters of the method - * @param returnType the return type of the method - */ - protected MethodProxy(String name, int modifiers, QualifiableProxy parent, Type[] parameters, Type returnType) { - super(name, Type.getMethodDescriptor(returnType, parameters), modifiers, parent); - this.parameters = Arrays.stream(parameters) - .map(t -> TypeProxy.from(t, 0)) - .toArray(TypeProxy[]::new); - this.returnType = TypeProxy.from(returnType, 0); - } - - /** - * A public constructor, builds a proxy from a {@link Method} - * obtained from reflection. - * @param m the {@link Method} object corresponding to this. - */ - public MethodProxy(Method m) { - this(m.getName(), - m.getModifiers(), - TypeProxy.from(m.getDeclaringClass()), - Type.getArgumentTypes(m), - Type.getReturnType(m) - ); - } - - /** - * Returns a new instance of {@link MethodProxy.Builder}. - * @param name the name of the method - * @return the builder object for method proxies - */ - public static Builder builder(String name) { - return new Builder(name); - } - - /** - * Indicates whether the given object is a proxy for the same element as this. - * @param obj the object to perform - * @return true if it's equal - */ - @Override - public boolean equals(Object obj) { - if(obj instanceof MethodProxy) { - MethodProxy m = (MethodProxy) obj; - return super.equals(obj) && m.returnType.equals(this.returnType) && Arrays.equals(m.parameters, this.parameters); - } else return false; - } - - /** - * A builder object for {@link MethodProxy}. - */ - public static class Builder extends AbstractProxy.Builder { - /** - * The parameters of the method. - */ - private final List parameters; - - /** - * The return type of the method. Defaults to void. - */ - private Type returnType; - - /** - * The constructor of the builder, used only internally. - * @param name the name of the method - */ - Builder(String name) { - super(name); - this.parameters = new ArrayList<>(); - this.returnType = Type.getType(void.class); - } - - /** - * Adds a parameter of a given type. - * @param fqn the fully qualified name of the parameter type - * @param arrayLevel the array level of the parameter type - * @return the builder's state after the change - */ - public Builder addParameter(String fqn, int arrayLevel) { - this.parameters.add(Type.getType(nameToDescriptor(fqn, arrayLevel))); - return this; - } - - /** - * Adds a parameter of a given type. - * @param paramType the {@link Class} object corresponding to - * the parameter type. - * @return the builder's state after the change - */ - public Builder addParameter(Class paramType) { - this.parameters.add(Type.getType(paramType)); - return this; - } - - /** - * Sets the return type to the given type. - * @param fqn the fully qualified name of the return type - * @param arrayLevel the array level of the return type - * @return the builder's state after the change - */ - public Builder setReturnType(String fqn, int arrayLevel) { - this.returnType = Type.getType(nameToDescriptor(fqn, arrayLevel)); - return this; - } - - /** - * Sets the parent class of this method to the one described by the - * fully qualified name and with the given modifiers. - * @param parentFQN the fully qualified name of the parent - * @param modifiers the modifiers of the parent - * @return the builder's state after the change - */ - public Builder setParent(String parentFQN, int modifiers) { - super.setParent(TypeProxy.from(parentFQN, 0, modifiers)); - return this; - } - - /** - * Sets the parent class of this method to the one described by the - * fully qualified name. - * @param parentFQN the fully qualified name of the parent - * @return the builder's state after the change - */ - public Builder setParent(String parentFQN) { - return this.setParent(parentFQN, 0); - } - - /** - * Sets the return type to the given type. - * @param returnType the {@link Class} object corresponding to - * the return type - * @return the builder's state after the change - */ - public Builder setReturnType(Class returnType) { - this.returnType = Type.getType(returnType); - return this; - } - - /** - * Builds a {@link MethodProxy} of the given kind. - * @return the built {@link MethodProxy} - */ - @Override - public MethodProxy build() { - return new MethodProxy( - this.name, - this.modifiers, - this.parent, - this.parameters.toArray(new Type[0]), - this.returnType); - } - } -} diff --git a/src/main/java/ftbsc/lll/proxies/PackageProxy.java b/src/main/java/ftbsc/lll/proxies/PackageProxy.java deleted file mode 100644 index fbfe6c0..0000000 --- a/src/main/java/ftbsc/lll/proxies/PackageProxy.java +++ /dev/null @@ -1,51 +0,0 @@ -package ftbsc.lll.proxies; - -/** - * A container for information about a package. - * @since 0.4.0 - */ -public class PackageProxy extends QualifiableProxy { - - /** - * The {@link PackageProxy} representing the root package. - */ - public static final PackageProxy ROOT = new PackageProxy(null, ""); - - /** - * The protected constructor, called only from {@link PackageProxy#from(String)}. - * @param parent the {@link PackageProxy} representing the parent - * @param fqn the fully-qualified name of this package - */ - protected PackageProxy(PackageProxy parent, String fqn) { - super(null, 0, parent, fqn); - } - - /** - * Builds a {@link PackageProxy} from its fully-qualified name. - * @param fqn the fully-qualified name of the package - * @return the built {@link PackageProxy} - */ - protected static PackageProxy from(String fqn) { - if(fqn == null || fqn.equals("")) return ROOT; - return new PackageProxy(from(extractParentFromFQN(fqn)), fqn); - } - - /** - * Builds a {@link PackageProxy} from a reflective {@link Package} object. - * @param p the {@link Package} object - * @return the built {@link PackageProxy} - */ - protected static PackageProxy from(Package p) { - return from(extractParentFromFQN(p.getName())); - } - - /** - * Indicates whether the given object is a proxy for the same element as this. - * @param obj the object to perform - * @return true if it's equal - */ - @Override - public boolean equals(Object obj) { - return obj instanceof PackageProxy && super.equals(obj); - } -} diff --git a/src/main/java/ftbsc/lll/proxies/ProxyType.java b/src/main/java/ftbsc/lll/proxies/ProxyType.java new file mode 100644 index 0000000..1fd8169 --- /dev/null +++ b/src/main/java/ftbsc/lll/proxies/ProxyType.java @@ -0,0 +1,11 @@ +package ftbsc.lll.proxies; + +/** + * An enum listing the various proxies. + */ +public enum ProxyType { + FIELD, + METHOD, + TYPE, + PACKAGE +} diff --git a/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java b/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java index 885ddc8..d245124 100644 --- a/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java +++ b/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java @@ -1,11 +1,7 @@ package ftbsc.lll.proxies; -import org.objectweb.asm.Type; - /** - * A container for information about an element which has a fully-qualified name. - * @see TypeProxy - * @see PackageProxy + * A proxy for elements who have a fully-qualified name. * @since 0.4.0 */ public abstract class QualifiableProxy extends AbstractProxy { @@ -26,9 +22,10 @@ public abstract class QualifiableProxy extends AbstractProxy { * @param modifiers the modifiers, as a packed int * @param parent the {@link QualifiableProxy} representing the parent of this element * @param fullyQualifiedName the FQN of the element + * @param proxyType the {@link ProxyType} being represented here */ - protected QualifiableProxy(String descriptor, int modifiers, QualifiableProxy parent, String fullyQualifiedName) { - super(extractSimpleNameFromFQN(fullyQualifiedName), descriptor, modifiers, parent); + protected QualifiableProxy(String descriptor, int modifiers, QualifiableProxy parent, String fullyQualifiedName, ProxyType proxyType) { + super(extractSimpleNameFromFQN(fullyQualifiedName), descriptor, modifiers, parent, proxyType); this.fullyQualifiedName = fullyQualifiedName; this.internalName = this.fullyQualifiedName.replace('.', '/'); } diff --git a/src/main/java/ftbsc/lll/proxies/TypeProxy.java b/src/main/java/ftbsc/lll/proxies/TypeProxy.java deleted file mode 100644 index f828f11..0000000 --- a/src/main/java/ftbsc/lll/proxies/TypeProxy.java +++ /dev/null @@ -1,196 +0,0 @@ -package ftbsc.lll.proxies; - -import org.objectweb.asm.Type; - -import java.lang.reflect.Modifier; - -import static ftbsc.lll.tools.DescriptorBuilder.nameToDescriptor; - -/** - * A container for information about classes to be used - * in ASM patching. - * @since 0.4.0 - */ -public class TypeProxy extends QualifiableProxy { - /** - * Whether this proxy represents a primitive. - */ - public final boolean primitive; - - /** - * Protected constructor, called only from the builder. - * @param name the name of the class - * @param descriptor the descriptor of the class - * @param modifiers the modifiers of the class - * @param parent the package containing this class - * @param primitive whether the proxy is a primitive - */ - protected TypeProxy(String name, String descriptor, int modifiers, String parent, boolean primitive) { - super(descriptor, modifiers, PackageProxy.from(parent), String.format("%s.%s", name, parent)); - this.primitive = primitive; - } - - /** - * Protected constructor, called only from the builder. - * @param name the name of the class - * @param descriptor the descriptor of the element - * @param modifiers the modifiers of the class - * @param primitive whether the proxy is a primitive - * @param containerClass the FQN of the parent class of the class - */ - protected TypeProxy(String name, String descriptor, int modifiers, QualifiableProxy containerClass, boolean primitive) { - super(descriptor, modifiers, containerClass, String.format("%s$%s", name, containerClass.fullyQualifiedName)); - this.primitive = primitive; - } - - /** - * Builds a {@link TypeProxy} from a {@link Type} and modifiers. - * @param type the {@link Type} representing this Class - * @param modifiers the modifiers of the class - * @return the builty {@link TypeProxy} - */ - public static TypeProxy from(Type type, int modifiers) { - while(type.getSort() == Type.ARRAY) - type = type.getElementType(); - String fqn = type.getInternalName().replace('/', '.'); - String simpleName = extractSimpleNameFromFQN(fqn); - String parent = extractParentFromFQN(fqn); - boolean primitive = type.getSort() < Type.ARRAY; - if(fqn.contains("$")) - return new TypeProxy(simpleName, type.getDescriptor(), modifiers, from(type, Modifier.PUBLIC), primitive); - else return new TypeProxy(simpleName, type.getDescriptor(), modifiers, parent, primitive); - } - - /** - * Builds a {@link TypeProxy} given only the fully-qualified name and modifiers. - * If present, parent classes will be assumed to have {@code public} as their - * only modifier. - * @param fqn the fully qualified name of the desired class - * @param arrayLevel the array level for this type - * @param modifiers the access modifiers of the desired class - * @return the built {@link TypeProxy} - */ - protected static TypeProxy from(String fqn, int arrayLevel, int modifiers) { - return from(Type.getObjectType(nameToDescriptor(fqn, arrayLevel)), modifiers); - } - - /** - * Builds a {@link TypeProxy} from a {@link Class} object. - * @param clazz the {@link Class} object representing the target class - * @return the built {@link TypeProxy} - */ - public static TypeProxy from(Class clazz) { - Class parentClass = clazz.getEnclosingClass(); - if(parentClass == null) - return new TypeProxy( - clazz.getSimpleName(), - Type.getDescriptor(clazz), - clazz.getModifiers(), - clazz.getPackage().getName(), - clazz.isPrimitive() - ); - else - return new TypeProxy( - clazz.getSimpleName(), - Type.getDescriptor(clazz), - clazz.getModifiers(), - from(parentClass), - clazz.isPrimitive() - ); - } - - /** - * Returns a new instance of {@link TypeProxy.Builder}. - * @param name the name of the class - * @return the builder object for class proxies - */ - public static Builder builder(String name) { - return new Builder(name); - } - - /** - * Indicates whether the given object is a proxy for the same element as this. - * @param obj the object to perform - * @return true if it's equal - */ - @Override - public boolean equals(Object obj) { - return obj instanceof TypeProxy && super.equals(obj); - } - - /** - * A builder object for {@link TypeProxy}. - */ - public static class Builder extends AbstractProxy.Builder { - - /** - * Whether the proxy represents a primitive. - */ - private boolean primitive; - - /** - * The constructor of the builder, used only internally. - * @param name the "simple name" of the class - */ - Builder(String name) { - super(name); - this.primitive = false; - } - - /** - * Sets this class as an inner class and sets the containing - * class to the given class object. - * @param containerClass the {@link Class} representing the - * container class - * @return the builder's state after the change - */ - public Builder setParent(Class containerClass) { - super.setParent(TypeProxy.from(containerClass)); - return this; - } - - /** - * Sets this class as an inner class and builds a {@link TypeProxy} - * from the given parent and modifiers. - * @param parentFQN the fully qualified name of the parent - * @param modifiers the modifiers of the parent (if it's a class) - * @param isParentPackage whether this parent should be interpreted as a package or class - * @return the builder's state after the change - */ - public Builder setParent(String parentFQN, int modifiers, boolean isParentPackage) { - super.setParent(isParentPackage ? PackageProxy.from(parentFQN) : TypeProxy.from(parentFQN, 0, modifiers)); - return this; - } - - /** - * Sets this class as an inner class and builds a {@link TypeProxy} - * from the given parent. - * @param parentFQN the fully qualified name of the parent - * @param isParentPackage whether this parent should be interpreted as a package or class - * @return the builder's state after the change - */ - public Builder setParent(String parentFQN, boolean isParentPackage) { - return this.setParent(parentFQN, 0, isParentPackage); - } - - /** - * Sets the primitive flag to true or false, to signal that the type here specified - * is a primitive. - * @param primitive the new state of the primitive flag - * @return the builder's state after the change - */ - public Builder setPrimitive(boolean primitive) { - this.primitive = primitive; - return this; - } - - /** - * Builds a {@link TypeProxy} of the given kind. - * @return the built {@link TypeProxy} - */ - @Override - public TypeProxy build() { - return new TypeProxy(this.name, this.descriptor, this.modifiers, this.parent, this.primitive); - } - } -} \ No newline at end of file diff --git a/src/main/java/ftbsc/lll/proxies/impl/FieldProxy.java b/src/main/java/ftbsc/lll/proxies/impl/FieldProxy.java new file mode 100644 index 0000000..ceb8277 --- /dev/null +++ b/src/main/java/ftbsc/lll/proxies/impl/FieldProxy.java @@ -0,0 +1,98 @@ +package ftbsc.lll.proxies.impl; + +import ftbsc.lll.proxies.AbstractProxy; +import ftbsc.lll.proxies.ProxyType; +import ftbsc.lll.proxies.QualifiableProxy; +import org.objectweb.asm.Type; + +import java.lang.reflect.Field; + +/** + * A container for information about class fields to be used + * in ASM patching. + * @since 0.3.0 + */ +public class FieldProxy extends AbstractProxy { + /** + * Protected constructor, called only from the builder. + * @param name the name of the field + * @param descriptor the descriptor of the field + * @param modifiers the modifiers of the field + * @param parent the {@link QualifiableProxy} for the parent + */ + protected FieldProxy(String name, String descriptor, int modifiers, QualifiableProxy parent) { + super(name, descriptor, modifiers, parent, ProxyType.FIELD); + } + + /** + * A public constructor, builds a proxy from a {@link Field} + * obtained from reflection. + * @param f the {@link Field} object corresponding to this. + */ + public FieldProxy(Field f) { + this(f.getName(), Type.getDescriptor(f.getType()), f.getModifiers(), TypeProxy.from(f.getDeclaringClass())); + } + + /** + * Returns a new instance of {@link FieldProxy.Builder}. + * @param name the name of the field + * @return the builder object for field proxies + */ + public static Builder builder(String name) { + return new Builder(name); + } + + /** + * Indicates whether the given object is a proxy for the same element as this. + * @param obj the object to perform + * @return true if it's equal + */ + @Override + public boolean equals(Object obj) { + return obj instanceof FieldProxy && super.equals(obj); + } + + /** + * A builder object for {@link FieldProxy}. + */ + public static class Builder extends AbstractProxy.Builder { + /** + * The constructor of the builder, used only internally. + * @param name the name of the field + */ + Builder(String name) { + super(name); + } + + /** + * Sets the parent class of this field to the one described by the + * fully qualified name and with the given modifiers. + * @param parentFQN the fully qualified name of the parent + * @param modifiers the modifiers of the parent + * @return the builder's state after the change + */ + public Builder setParent(String parentFQN, int modifiers) { + super.setParent(TypeProxy.from(parentFQN, 0, modifiers)); + return this; + } + + /** + * Sets the parent class of this field to the one described by the + * fully qualified name. + * @param parentFQN the fully qualified name of the parent + * @return the builder's state after the change + */ + public Builder setParent(String parentFQN) { + return this.setParent(parentFQN, 0); + } + + /** + * Builds a {@link FieldProxy} of the given kind. + * @return the built {@link FieldProxy} + */ + @Override + public FieldProxy build() { + return new FieldProxy(this.name, this.descriptor, this.modifiers, this.parent); + } + } +} diff --git a/src/main/java/ftbsc/lll/proxies/impl/MethodProxy.java b/src/main/java/ftbsc/lll/proxies/impl/MethodProxy.java new file mode 100644 index 0000000..3710d36 --- /dev/null +++ b/src/main/java/ftbsc/lll/proxies/impl/MethodProxy.java @@ -0,0 +1,188 @@ +package ftbsc.lll.proxies.impl; + +import ftbsc.lll.proxies.AbstractProxy; +import ftbsc.lll.proxies.ProxyType; +import ftbsc.lll.proxies.QualifiableProxy; +import org.objectweb.asm.Type; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static ftbsc.lll.tools.DescriptorBuilder.nameToDescriptor; + +/** + * A container for information about class methods to be used + * in ASM patching. + * @since 0.3.0 + */ +public class MethodProxy extends AbstractProxy { + + /** + * An array of {@link TypeProxy} each representing the parameters of the method. + */ + public final TypeProxy[] parameters; + + /** + * The {@link TypeProxy} for the return type of the method. + */ + public final TypeProxy returnType; + + /** + * A protected constructor, called only from the builder. + * @param name the name of the method + * @param modifiers the modifiers of the method + * @param parent the {@link QualifiableProxy} for the parent + * @param parameters the parameters of the method + * @param returnType the return type of the method + */ + protected MethodProxy(String name, int modifiers, QualifiableProxy parent, Type[] parameters, Type returnType) { + super(name, Type.getMethodDescriptor(returnType, parameters), modifiers, parent, ProxyType.METHOD); + this.parameters = Arrays.stream(parameters) + .map(t -> TypeProxy.from(t, 0)) + .toArray(TypeProxy[]::new); + this.returnType = TypeProxy.from(returnType, 0); + } + + /** + * A public constructor, builds a proxy from a {@link Method} + * obtained from reflection. + * @param m the {@link Method} object corresponding to this. + */ + public MethodProxy(Method m) { + this(m.getName(), + m.getModifiers(), + TypeProxy.from(m.getDeclaringClass()), + Type.getArgumentTypes(m), + Type.getReturnType(m) + ); + } + + /** + * Returns a new instance of {@link MethodProxy.Builder}. + * @param name the name of the method + * @return the builder object for method proxies + */ + public static Builder builder(String name) { + return new Builder(name); + } + + /** + * Indicates whether the given object is a proxy for the same element as this. + * @param obj the object to perform + * @return true if it's equal + */ + @Override + public boolean equals(Object obj) { + if(obj instanceof MethodProxy) { + MethodProxy m = (MethodProxy) obj; + return super.equals(obj) && m.returnType.equals(this.returnType) && Arrays.equals(m.parameters, this.parameters); + } else return false; + } + + /** + * A builder object for {@link MethodProxy}. + */ + public static class Builder extends AbstractProxy.Builder { + /** + * The parameters of the method. + */ + private final List parameters; + + /** + * The return type of the method. Defaults to void. + */ + private Type returnType; + + /** + * The constructor of the builder, used only internally. + * @param name the name of the method + */ + Builder(String name) { + super(name); + this.parameters = new ArrayList<>(); + this.returnType = Type.getType(void.class); + } + + /** + * Adds a parameter of a given type. + * @param fqn the fully qualified name of the parameter type + * @param arrayLevel the array level of the parameter type + * @return the builder's state after the change + */ + public Builder addParameter(String fqn, int arrayLevel) { + this.parameters.add(Type.getType(nameToDescriptor(fqn, arrayLevel))); + return this; + } + + /** + * Adds a parameter of a given type. + * @param paramType the {@link Class} object corresponding to + * the parameter type. + * @return the builder's state after the change + */ + public Builder addParameter(Class paramType) { + this.parameters.add(Type.getType(paramType)); + return this; + } + + /** + * Sets the return type to the given type. + * @param fqn the fully qualified name of the return type + * @param arrayLevel the array level of the return type + * @return the builder's state after the change + */ + public Builder setReturnType(String fqn, int arrayLevel) { + this.returnType = Type.getType(nameToDescriptor(fqn, arrayLevel)); + return this; + } + + /** + * Sets the parent class of this method to the one described by the + * fully qualified name and with the given modifiers. + * @param parentFQN the fully qualified name of the parent + * @param modifiers the modifiers of the parent + * @return the builder's state after the change + */ + public Builder setParent(String parentFQN, int modifiers) { + super.setParent(TypeProxy.from(parentFQN, 0, modifiers)); + return this; + } + + /** + * Sets the parent class of this method to the one described by the + * fully qualified name. + * @param parentFQN the fully qualified name of the parent + * @return the builder's state after the change + */ + public Builder setParent(String parentFQN) { + return this.setParent(parentFQN, 0); + } + + /** + * Sets the return type to the given type. + * @param returnType the {@link Class} object corresponding to + * the return type + * @return the builder's state after the change + */ + public Builder setReturnType(Class returnType) { + this.returnType = Type.getType(returnType); + return this; + } + + /** + * Builds a {@link MethodProxy} of the given kind. + * @return the built {@link MethodProxy} + */ + @Override + public MethodProxy build() { + return new MethodProxy( + this.name, + this.modifiers, + this.parent, + this.parameters.toArray(new Type[0]), + this.returnType); + } + } +} diff --git a/src/main/java/ftbsc/lll/proxies/impl/PackageProxy.java b/src/main/java/ftbsc/lll/proxies/impl/PackageProxy.java new file mode 100644 index 0000000..5989da3 --- /dev/null +++ b/src/main/java/ftbsc/lll/proxies/impl/PackageProxy.java @@ -0,0 +1,54 @@ +package ftbsc.lll.proxies.impl; + +import ftbsc.lll.proxies.ProxyType; +import ftbsc.lll.proxies.QualifiableProxy; + +/** + * A container for information about a package. + * @since 0.4.0 + */ +public class PackageProxy extends QualifiableProxy { + + /** + * The {@link PackageProxy} representing the root package. + */ + public static final PackageProxy ROOT = new PackageProxy(null, ""); + + /** + * The protected constructor, called only from {@link PackageProxy#from(String)}. + * @param parent the {@link PackageProxy} representing the parent + * @param fqn the fully-qualified name of this package + */ + protected PackageProxy(PackageProxy parent, String fqn) { + super(null, 0, parent, fqn, ProxyType.PACKAGE); + } + + /** + * Builds a {@link PackageProxy} from its fully-qualified name. + * @param fqn the fully-qualified name of the package + * @return the built {@link PackageProxy} + */ + protected static PackageProxy from(String fqn) { + if(fqn == null || fqn.equals("")) return ROOT; + return new PackageProxy(from(extractParentFromFQN(fqn)), fqn); + } + + /** + * Builds a {@link PackageProxy} from a reflective {@link Package} object. + * @param p the {@link Package} object + * @return the built {@link PackageProxy} + */ + protected static PackageProxy from(Package p) { + return from(extractParentFromFQN(p.getName())); + } + + /** + * Indicates whether the given object is a proxy for the same element as this. + * @param obj the object to perform + * @return true if it's equal + */ + @Override + public boolean equals(Object obj) { + return obj instanceof PackageProxy && super.equals(obj); + } +} diff --git a/src/main/java/ftbsc/lll/proxies/impl/TypeProxy.java b/src/main/java/ftbsc/lll/proxies/impl/TypeProxy.java new file mode 100644 index 0000000..9f613b0 --- /dev/null +++ b/src/main/java/ftbsc/lll/proxies/impl/TypeProxy.java @@ -0,0 +1,199 @@ +package ftbsc.lll.proxies.impl; + +import ftbsc.lll.proxies.AbstractProxy; +import ftbsc.lll.proxies.ProxyType; +import ftbsc.lll.proxies.QualifiableProxy; +import org.objectweb.asm.Type; + +import java.lang.reflect.Modifier; + +import static ftbsc.lll.tools.DescriptorBuilder.nameToDescriptor; + +/** + * A container for information about classes to be used + * in ASM patching. + * @since 0.4.0 + */ +public class TypeProxy extends QualifiableProxy { + /** + * Whether this proxy represents a primitive. + */ + public final boolean primitive; + + /** + * Protected constructor, called only from the builder. + * @param name the name of the class + * @param descriptor the descriptor of the class + * @param modifiers the modifiers of the class + * @param parent the package containing this class + * @param primitive whether the proxy is a primitive + */ + protected TypeProxy(String name, String descriptor, int modifiers, String parent, boolean primitive) { + super(descriptor, modifiers, PackageProxy.from(parent), String.format("%s.%s", name, parent), ProxyType.TYPE); + this.primitive = primitive; + } + + /** + * Protected constructor, called only from the builder. + * @param name the name of the class + * @param descriptor the descriptor of the element + * @param modifiers the modifiers of the class + * @param primitive whether the proxy is a primitive + * @param containerClass the FQN of the parent class of the class + */ + protected TypeProxy(String name, String descriptor, int modifiers, QualifiableProxy containerClass, boolean primitive) { + super(descriptor, modifiers, containerClass, String.format("%s$%s", name, containerClass.fullyQualifiedName), ProxyType.TYPE); + this.primitive = primitive; + } + + /** + * Builds a {@link TypeProxy} from a {@link Type} and modifiers. + * @param type the {@link Type} representing this Class + * @param modifiers the modifiers of the class + * @return the builty {@link TypeProxy} + */ + public static TypeProxy from(Type type, int modifiers) { + while(type.getSort() == Type.ARRAY) + type = type.getElementType(); + String fqn = type.getInternalName().replace('/', '.'); + String simpleName = extractSimpleNameFromFQN(fqn); + String parent = extractParentFromFQN(fqn); + boolean primitive = type.getSort() < Type.ARRAY; + if(fqn.contains("$")) + return new TypeProxy(simpleName, type.getDescriptor(), modifiers, from(type, Modifier.PUBLIC), primitive); + else return new TypeProxy(simpleName, type.getDescriptor(), modifiers, parent, primitive); + } + + /** + * Builds a {@link TypeProxy} given only the fully-qualified name and modifiers. + * If present, parent classes will be assumed to have {@code public} as their + * only modifier. + * @param fqn the fully qualified name of the desired class + * @param arrayLevel the array level for this type + * @param modifiers the access modifiers of the desired class + * @return the built {@link TypeProxy} + */ + protected static TypeProxy from(String fqn, int arrayLevel, int modifiers) { + return from(Type.getObjectType(nameToDescriptor(fqn, arrayLevel)), modifiers); + } + + /** + * Builds a {@link TypeProxy} from a {@link Class} object. + * @param clazz the {@link Class} object representing the target class + * @return the built {@link TypeProxy} + */ + public static TypeProxy from(Class clazz) { + Class parentClass = clazz.getEnclosingClass(); + if(parentClass == null) + return new TypeProxy( + clazz.getSimpleName(), + Type.getDescriptor(clazz), + clazz.getModifiers(), + clazz.getPackage().getName(), + clazz.isPrimitive() + ); + else + return new TypeProxy( + clazz.getSimpleName(), + Type.getDescriptor(clazz), + clazz.getModifiers(), + from(parentClass), + clazz.isPrimitive() + ); + } + + /** + * Returns a new instance of {@link TypeProxy.Builder}. + * @param name the name of the class + * @return the builder object for class proxies + */ + public static Builder builder(String name) { + return new Builder(name); + } + + /** + * Indicates whether the given object is a proxy for the same element as this. + * @param obj the object to perform + * @return true if it's equal + */ + @Override + public boolean equals(Object obj) { + return obj instanceof TypeProxy && super.equals(obj); + } + + /** + * A builder object for {@link TypeProxy}. + */ + public static class Builder extends AbstractProxy.Builder { + + /** + * Whether the proxy represents a primitive. + */ + private boolean primitive; + + /** + * The constructor of the builder, used only internally. + * @param name the "simple name" of the class + */ + Builder(String name) { + super(name); + this.primitive = false; + } + + /** + * Sets this class as an inner class and sets the containing + * class to the given class object. + * @param containerClass the {@link Class} representing the + * container class + * @return the builder's state after the change + */ + public Builder setParent(Class containerClass) { + super.setParent(TypeProxy.from(containerClass)); + return this; + } + + /** + * Sets this class as an inner class and builds a {@link TypeProxy} + * from the given parent and modifiers. + * @param parentFQN the fully qualified name of the parent + * @param modifiers the modifiers of the parent (if it's a class) + * @param isParentPackage whether this parent should be interpreted as a package or class + * @return the builder's state after the change + */ + public Builder setParent(String parentFQN, int modifiers, boolean isParentPackage) { + super.setParent(isParentPackage ? PackageProxy.from(parentFQN) : TypeProxy.from(parentFQN, 0, modifiers)); + return this; + } + + /** + * Sets this class as an inner class and builds a {@link TypeProxy} + * from the given parent. + * @param parentFQN the fully qualified name of the parent + * @param isParentPackage whether this parent should be interpreted as a package or class + * @return the builder's state after the change + */ + public Builder setParent(String parentFQN, boolean isParentPackage) { + return this.setParent(parentFQN, 0, isParentPackage); + } + + /** + * Sets the primitive flag to true or false, to signal that the type here specified + * is a primitive. + * @param primitive the new state of the primitive flag + * @return the builder's state after the change + */ + public Builder setPrimitive(boolean primitive) { + this.primitive = primitive; + return this; + } + + /** + * Builds a {@link TypeProxy} of the given kind. + * @return the built {@link TypeProxy} + */ + @Override + public TypeProxy build() { + return new TypeProxy(this.name, this.descriptor, this.modifiers, this.parent, this.primitive); + } + } +} \ No newline at end of file diff --git a/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java b/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java index 068ade0..d1ac595 100644 --- a/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java +++ b/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java @@ -1,6 +1,6 @@ package ftbsc.lll.tools.nodes; -import ftbsc.lll.proxies.FieldProxy; +import ftbsc.lll.proxies.impl.FieldProxy; import org.objectweb.asm.tree.FieldInsnNode; /** diff --git a/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java b/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java index 01549a8..73a26d7 100644 --- a/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java +++ b/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java @@ -1,6 +1,6 @@ package ftbsc.lll.tools.nodes; -import ftbsc.lll.proxies.MethodProxy; +import ftbsc.lll.proxies.impl.MethodProxy; import org.objectweb.asm.tree.MethodInsnNode; /** diff --git a/src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java b/src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java index e5b5f2a..9e78dc9 100644 --- a/src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java +++ b/src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java @@ -1,6 +1,6 @@ package ftbsc.lll.tools.nodes; -import ftbsc.lll.proxies.TypeProxy; +import ftbsc.lll.proxies.impl.TypeProxy; import org.objectweb.asm.tree.TypeInsnNode; /** -- cgit v1.2.3-56-ga3b1