mirror of
https://github.com/zaaarf/lillero.git
synced 2024-11-21 23:14:51 +01:00
Merge branch 'version4' into dev
This commit is contained in:
commit
b8cd398fd5
13 changed files with 728 additions and 419 deletions
|
@ -1,68 +1,71 @@
|
||||||
package ftbsc.lll.proxies;
|
package ftbsc.lll.proxies;
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract proxy class, implementing common aspects
|
* Abstract proxy class, implementing common aspects.
|
||||||
* of {@link MethodProxy} and {@link FieldProxy}.
|
|
||||||
* @since 0.3.0
|
* @since 0.3.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractProxy {
|
public abstract class AbstractProxy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the corresponding class member.
|
* Which type of proxy this is.
|
||||||
*/
|
*/
|
||||||
private final String name;
|
public final ProxyType proxyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the corresponding element.
|
||||||
|
*/
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The descriptor for this element.
|
||||||
|
*/
|
||||||
|
public final String descriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The fully qualified name (i.e. java.lang.String) of
|
* The fully qualified name (i.e. java.lang.String) of
|
||||||
* the parent class.
|
* the parent class.
|
||||||
*/
|
*/
|
||||||
private final String parent;
|
public final QualifiableProxy parent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The modifiers of the member, as a packed int.
|
* The modifiers of the member, as a packed int
|
||||||
* @see java.lang.reflect.Modifier
|
|
||||||
*/
|
|
||||||
private final int modifiers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the name of the item
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the modifiers of the member, as a packed int
|
|
||||||
* @see Modifier
|
* @see Modifier
|
||||||
*/
|
*/
|
||||||
public int getModifiers() {
|
public final int modifiers;
|
||||||
return this.modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the fully qualified name of the parent class
|
|
||||||
*/
|
|
||||||
public String getParent() {
|
|
||||||
return this.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the descriptor of the member
|
|
||||||
*/
|
|
||||||
public abstract String getDescriptor();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The private constructor, should be called by all classes extending this in theirs.
|
* The private constructor, should be called by all classes extending this in theirs.
|
||||||
* @param name the name of the member
|
* @param name the name of the element
|
||||||
|
* @param descriptor the descriptor for the element
|
||||||
* @param modifiers the modifiers, as a packed int
|
* @param modifiers the modifiers, as a packed int
|
||||||
* @param parent the FQN of the parent class
|
* @param parent the FQN of the parent class
|
||||||
|
* @param proxyType the {@link ProxyType} being represented here
|
||||||
*/
|
*/
|
||||||
protected AbstractProxy(String name, int modifiers, String parent) {
|
protected AbstractProxy(String name, String descriptor, int modifiers, QualifiableProxy parent, ProxyType proxyType) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.descriptor = descriptor;
|
||||||
this.modifiers = modifiers;
|
this.modifiers = modifiers;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
this.proxyType = proxyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 AbstractProxy) {
|
||||||
|
AbstractProxy p = (AbstractProxy) obj;
|
||||||
|
return p.parent.equals(this.parent)
|
||||||
|
&& p.name.equals(this.name)
|
||||||
|
&& p.modifiers == this.modifiers
|
||||||
|
&& p.descriptor.equals(this.descriptor);
|
||||||
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,38 +75,34 @@ public abstract class AbstractProxy {
|
||||||
public abstract static class Builder<T extends AbstractProxy> {
|
public abstract static class Builder<T extends AbstractProxy> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the member.
|
* The name of the element.
|
||||||
*/
|
*/
|
||||||
protected final String name;
|
protected String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The modifiers of the member, as a packed int.
|
* The modifiers of the element, as a packed int.
|
||||||
*/
|
*/
|
||||||
protected int modifiers;
|
protected int modifiers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The fully qualified name of the parent.
|
* The fully qualified name of the parent.
|
||||||
*/
|
*/
|
||||||
protected String parent;
|
protected QualifiableProxy parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The descriptor of the element.
|
||||||
|
*/
|
||||||
|
protected String descriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor.
|
* The constructor.
|
||||||
* @param name the name of the member
|
* @param name the name of the element
|
||||||
*/
|
*/
|
||||||
protected Builder(String name) {
|
protected Builder(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.modifiers = 0;
|
this.modifiers = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param parentFQN the fully qualified name of the parent
|
|
||||||
* @return the current state of the builder
|
|
||||||
*/
|
|
||||||
public Builder<T> setParent(String parentFQN) {
|
|
||||||
this.parent = parentFQN;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param newModifier the modifier to add
|
* @param newModifier the modifier to add
|
||||||
* @return the current state of the builder
|
* @return the current state of the builder
|
||||||
|
@ -117,11 +116,38 @@ public abstract class AbstractProxy {
|
||||||
* @param newModifier the new modifier value
|
* @param newModifier the new modifier value
|
||||||
* @return the current state of the builder
|
* @return the current state of the builder
|
||||||
*/
|
*/
|
||||||
public Builder<T> setModifier(int newModifier) {
|
public Builder<T> setModifiers(int newModifier) {
|
||||||
this.modifiers = newModifier;
|
this.modifiers = newModifier;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parent the {@link QualifiableProxy} representing the parent
|
||||||
|
* @return the current state of the builder
|
||||||
|
*/
|
||||||
|
public Builder<T> setParent(QualifiableProxy parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets {@link Type} for this element from the descriptor, passed as a {@link String}.
|
||||||
|
* @param descriptor the descriptor passed as a {@link String}
|
||||||
|
* @return the builder's state after the change
|
||||||
|
*/
|
||||||
|
public Builder<T> setDescriptor(String descriptor) {
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type the {@link Type} corresponding to the element
|
||||||
|
* @return the current state of the builder
|
||||||
|
*/
|
||||||
|
public Builder<T> setType(Type type) {
|
||||||
|
return this.setDescriptor(type.getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the built proxy object
|
* @return the built proxy object
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
package ftbsc.lll.proxies;
|
|
||||||
|
|
||||||
import ftbsc.lll.tools.DescriptorBuilder;
|
|
||||||
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 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the field's type.
|
|
||||||
*/
|
|
||||||
private final String typeDescriptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(), f.getModifiers(), Type.getInternalName(f.getDeclaringClass()));
|
|
||||||
this.typeDescriptor = Type.getDescriptor(f.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A protected constructor, called only from the builder.
|
|
||||||
* @param name the name of the field
|
|
||||||
* @param modifiers the modifiers of the field
|
|
||||||
* @param parent the FQN of the parent class of the field
|
|
||||||
* @param typeDescriptor the type descriptor of the field
|
|
||||||
*/
|
|
||||||
FieldProxy(String name, int modifiers, String parent, String typeDescriptor) {
|
|
||||||
super(name, modifiers, parent);
|
|
||||||
this.typeDescriptor = typeDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the field's type descriptor
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getDescriptor() {
|
|
||||||
return typeDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder object for {@link FieldProxy}.
|
|
||||||
*/
|
|
||||||
public static class Builder extends AbstractProxy.Builder<FieldProxy> {
|
|
||||||
/**
|
|
||||||
* The descriptor of the field's type.
|
|
||||||
*/
|
|
||||||
private String typeDescriptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor of the builder, used only internally.
|
|
||||||
* @param name the name of the field
|
|
||||||
*/
|
|
||||||
Builder(String name) {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the descriptor of the field type to the given {@link String}.
|
|
||||||
* @param typeDescriptor the descriptor of the field type
|
|
||||||
* @return the builder's state after the change
|
|
||||||
*/
|
|
||||||
public Builder setDescriptor(String typeDescriptor) {
|
|
||||||
this.typeDescriptor = typeDescriptor;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the descriptor of the field type to match the give {@link Class}.
|
|
||||||
* @param fqn the fully qualified name of the field type
|
|
||||||
* @param arrayLevel the array level of the field type
|
|
||||||
* @return the builder's state after the change
|
|
||||||
*/
|
|
||||||
public Builder setType(String fqn, int arrayLevel) {
|
|
||||||
this.typeDescriptor = DescriptorBuilder.nameToDescriptor(fqn, arrayLevel);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the descriptor of the field type to match the give {@link Class}.
|
|
||||||
* @param type a {@link Class} object representing the field type
|
|
||||||
* @return the builder's state after the change
|
|
||||||
*/
|
|
||||||
public Builder setType(Class<?> type) {
|
|
||||||
this.typeDescriptor = Type.getDescriptor(type);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a {@link FieldProxy} of the given kind.
|
|
||||||
* @return the built {@link FieldProxy}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public FieldProxy build() {
|
|
||||||
return new FieldProxy(this.name, this.modifiers, this.parent, this.typeDescriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,230 +0,0 @@
|
||||||
package ftbsc.lll.proxies;
|
|
||||||
|
|
||||||
import ftbsc.lll.tools.DescriptorBuilder;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A container for information about class methods to be used
|
|
||||||
* in ASM patching.
|
|
||||||
* @since 0.3.0
|
|
||||||
*/
|
|
||||||
public class MethodProxy extends AbstractProxy {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The parameters of the method.
|
|
||||||
* It holds fully qualified names for objects, and {@link Class}
|
|
||||||
* objects for primitives.
|
|
||||||
*/
|
|
||||||
private final Object[] parameters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The return type of the method.
|
|
||||||
* It contains if it's an object, or a {@link Class}
|
|
||||||
* object for primitives.
|
|
||||||
*/
|
|
||||||
private final Object returnType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Caches the the descriptor after generating it once for
|
|
||||||
* performance.
|
|
||||||
*/
|
|
||||||
private String descriptorCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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) {
|
|
||||||
super(m.getName(), m.getModifiers(), Type.getInternalName(m.getDeclaringClass()));
|
|
||||||
List<Object> parameters = new ArrayList<>();
|
|
||||||
for(Class<?> p : m.getParameterTypes())
|
|
||||||
parameters.add(p.isPrimitive() ? p : new TypeContainer(p));
|
|
||||||
this.parameters = parameters.toArray();
|
|
||||||
Class<?> returnType = m.getReturnType();
|
|
||||||
this.returnType = returnType.isPrimitive() ? returnType : new TypeContainer(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 FQN of the parent class of the method
|
|
||||||
* @param parameters the parameters of the method
|
|
||||||
* @param returnType the return type of the method
|
|
||||||
*/
|
|
||||||
protected MethodProxy(String name, int modifiers, String parent, Object[] parameters, Object returnType) {
|
|
||||||
super(name, modifiers, parent);
|
|
||||||
this.parameters = parameters;
|
|
||||||
this.returnType = returnType;
|
|
||||||
this.descriptorCache = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds (or returns from cache if present)
|
|
||||||
* the method's descriptor.
|
|
||||||
* @return the method's descriptor
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getDescriptor() {
|
|
||||||
if(this.descriptorCache != null)
|
|
||||||
return this.descriptorCache;
|
|
||||||
DescriptorBuilder b = new DescriptorBuilder();
|
|
||||||
for(Object p : this.parameters)
|
|
||||||
addTypeToDescriptorBuilder(b, p, false);
|
|
||||||
addTypeToDescriptorBuilder(b, this.returnType, true);
|
|
||||||
this.descriptorCache = b.build();
|
|
||||||
return this.descriptorCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A static method used internally to detect and correctly insert a
|
|
||||||
* {@link TypeContainer} into a {@link DescriptorBuilder}.
|
|
||||||
* @param b the {@link DescriptorBuilder}
|
|
||||||
* @param p the {@link TypeContainer}
|
|
||||||
* @param isReturnType whether it should be inserted as a return type
|
|
||||||
*/
|
|
||||||
private static void addTypeToDescriptorBuilder(DescriptorBuilder b, Object p, boolean isReturnType) {
|
|
||||||
if(p instanceof TypeContainer) {
|
|
||||||
TypeContainer param = (TypeContainer) p;
|
|
||||||
if(isReturnType)
|
|
||||||
b.setReturnType(param.fqn, param.arrayLevel);
|
|
||||||
else b.addParameter(param.fqn, param.arrayLevel);
|
|
||||||
} else {
|
|
||||||
if(isReturnType)
|
|
||||||
b.setReturnType((Class<?>) p);
|
|
||||||
else b.addParameter((Class<?>) p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder object for {@link MethodProxy}.
|
|
||||||
*/
|
|
||||||
public static class Builder extends AbstractProxy.Builder<MethodProxy> {
|
|
||||||
/**
|
|
||||||
* The parameters of the method.
|
|
||||||
*/
|
|
||||||
private final List<Object> parameters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The return type of the method. Defaults to void.
|
|
||||||
*/
|
|
||||||
private Object 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 = 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(new TypeContainer(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(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 = new TypeContainer(fqn, arrayLevel);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 = returnType;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a {@link MethodProxy} of the given kind.
|
|
||||||
* @return the built {@link MethodProxy}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public MethodProxy build() {
|
|
||||||
return new MethodProxy(name, modifiers, parent, parameters.toArray(), returnType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A container class, holding information about a given type.
|
|
||||||
*/
|
|
||||||
protected static class TypeContainer {
|
|
||||||
/**
|
|
||||||
* The fully qualified name of the type.
|
|
||||||
*/
|
|
||||||
public final String fqn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The array level of the type.
|
|
||||||
*/
|
|
||||||
public final int arrayLevel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public constructor for the class.
|
|
||||||
* @param fqn the fully qualified name of the type
|
|
||||||
* @param arrayLevel the array level of the type
|
|
||||||
*/
|
|
||||||
public TypeContainer(String fqn, int arrayLevel) {
|
|
||||||
this.fqn = fqn;
|
|
||||||
this.arrayLevel = arrayLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public constructor for the class, extracting the
|
|
||||||
* necessary information from a {@link Class} object.
|
|
||||||
* @param clazz the class object
|
|
||||||
*/
|
|
||||||
public TypeContainer(Class<?> clazz) {
|
|
||||||
int arrayLevel = 0;
|
|
||||||
while(clazz.isArray()) {
|
|
||||||
arrayLevel++;
|
|
||||||
clazz = clazz.getComponentType();
|
|
||||||
}
|
|
||||||
this.arrayLevel = arrayLevel;
|
|
||||||
this.fqn = clazz.getCanonicalName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
11
src/main/java/ftbsc/lll/proxies/ProxyType.java
Normal file
11
src/main/java/ftbsc/lll/proxies/ProxyType.java
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package ftbsc.lll.proxies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enum listing the various proxies.
|
||||||
|
*/
|
||||||
|
public enum ProxyType {
|
||||||
|
FIELD,
|
||||||
|
METHOD,
|
||||||
|
TYPE,
|
||||||
|
PACKAGE
|
||||||
|
}
|
67
src/main/java/ftbsc/lll/proxies/QualifiableProxy.java
Normal file
67
src/main/java/ftbsc/lll/proxies/QualifiableProxy.java
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package ftbsc.lll.proxies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A proxy for elements who have a fully-qualified name.
|
||||||
|
* @since 0.4.0
|
||||||
|
*/
|
||||||
|
public abstract class QualifiableProxy extends AbstractProxy {
|
||||||
|
/**
|
||||||
|
* The fully-qualified name of the element represented by this proxy.
|
||||||
|
*/
|
||||||
|
public final String fullyQualifiedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "internal name" (fully-qualified with slashes) of the element
|
||||||
|
* represented by this proxy.
|
||||||
|
*/
|
||||||
|
public final String internalName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The protected constructor, should be called by all classes extending this in theirs.
|
||||||
|
* @param descriptor the descriptor for the element
|
||||||
|
* @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, ProxyType proxyType) {
|
||||||
|
super(extractSimpleNameFromFQN(fullyQualifiedName), descriptor, modifiers, parent, proxyType);
|
||||||
|
this.fullyQualifiedName = fullyQualifiedName;
|
||||||
|
this.internalName = this.fullyQualifiedName.replace('.', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link String} containing the FQN of the parent element
|
||||||
|
* to this, which may represent a package or class.
|
||||||
|
* @param fqn the fully qualified name of the element
|
||||||
|
* @return the parent, or null if the parent was the root element
|
||||||
|
*/
|
||||||
|
protected static String extractParentFromFQN(String fqn) {
|
||||||
|
String lastSeparator = fqn.contains("$") ? "\\$" : "\\.";
|
||||||
|
String[] split = fqn.split(lastSeparator);
|
||||||
|
if(split.length == 1) return null;
|
||||||
|
return fqn.substring(0, split[split.length - 1].length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link String} containing the simple name of the element.
|
||||||
|
* @param fqn the fully qualified name of the element
|
||||||
|
* @return the simple name
|
||||||
|
*/
|
||||||
|
protected static String extractSimpleNameFromFQN(String fqn) {
|
||||||
|
String lastSeparator = fqn.contains("$") ? "\\$" : "\\.";
|
||||||
|
String[] split = fqn.split(lastSeparator);
|
||||||
|
if(split.length == 1) return fqn;
|
||||||
|
else return split[split.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 QualifiableProxy && super.equals(obj) && ((QualifiableProxy) obj).fullyQualifiedName.equals(fullyQualifiedName);
|
||||||
|
}
|
||||||
|
}
|
98
src/main/java/ftbsc/lll/proxies/impl/FieldProxy.java
Normal file
98
src/main/java/ftbsc/lll/proxies/impl/FieldProxy.java
Normal file
|
@ -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<FieldProxy> {
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
188
src/main/java/ftbsc/lll/proxies/impl/MethodProxy.java
Normal file
188
src/main/java/ftbsc/lll/proxies/impl/MethodProxy.java
Normal file
|
@ -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<MethodProxy> {
|
||||||
|
/**
|
||||||
|
* The parameters of the method.
|
||||||
|
*/
|
||||||
|
private final List<Type> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
src/main/java/ftbsc/lll/proxies/impl/PackageProxy.java
Normal file
54
src/main/java/ftbsc/lll/proxies/impl/PackageProxy.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
199
src/main/java/ftbsc/lll/proxies/impl/TypeProxy.java
Normal file
199
src/main/java/ftbsc/lll/proxies/impl/TypeProxy.java
Normal file
|
@ -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<TypeProxy> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,16 +26,15 @@ public class DescriptorBuilder {
|
||||||
* Initialises default values.
|
* Initialises default values.
|
||||||
*/
|
*/
|
||||||
public DescriptorBuilder() {
|
public DescriptorBuilder() {
|
||||||
|
|
||||||
this.returnType = Type.getDescriptor(void.class);
|
this.returnType = Type.getDescriptor(void.class);
|
||||||
this.params = new ArrayList<>();
|
this.params = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the return type to the given type.
|
* Sets the return type to the given type.
|
||||||
* WARNING: will most likely cause problems if used with objects outside the
|
* Passing a {@link Class} may cause problems if used with objects outside the Java
|
||||||
* Java SDK. Pass the fully qualified name as a String rather than the Class
|
* SDK. Pass the fully qualified name as a {@link String} rather than the {@link Class}
|
||||||
* object for non-standard types (such as Minecraft classes).
|
* object for non-standard types.
|
||||||
* @param returnType the Class object corresponding to the return type
|
* @param returnType the Class object corresponding to the return type
|
||||||
* @return the builder's state after the change
|
* @return the builder's state after the change
|
||||||
*/
|
*/
|
||||||
|
@ -72,9 +71,9 @@ public class DescriptorBuilder {
|
||||||
/**
|
/**
|
||||||
* Adds a parameter of the given class type to the method.
|
* Adds a parameter of the given class type to the method.
|
||||||
* Parameter order matters.
|
* Parameter order matters.
|
||||||
* WARNING: will most likely cause problems if used with objects outside the
|
* Passing a {@link Class} may cause problems if used with objects outside the Java
|
||||||
* Java SDK. Pass the fully qualified name as a String rather than the Class
|
* SDK. Pass the fully qualified name as a {@link String} rather than the {@link Class}
|
||||||
* object for non-standard types (such as Minecraft classes).
|
* object for non-standard types.
|
||||||
* @param param the Class object corresponding to the parameter
|
* @param param the Class object corresponding to the parameter
|
||||||
* @return the builder's state after the change
|
* @return the builder's state after the change
|
||||||
*/
|
*/
|
||||||
|
@ -113,7 +112,7 @@ public class DescriptorBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the descriptor into a string.
|
* Builds the descriptor into a string.
|
||||||
* Example result: int m(Object[] o) -> ([Ljava/lang/Object;)I
|
* Example result: {@code int m(Object[] o)} becomes {@code ([Ljava/lang/Object;)I}
|
||||||
* @return the resulting descriptor
|
* @return the resulting descriptor
|
||||||
*/
|
*/
|
||||||
public String build() {
|
public String build() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package ftbsc.lll.tools.nodes;
|
package ftbsc.lll.tools.nodes;
|
||||||
|
|
||||||
import ftbsc.lll.proxies.FieldProxy;
|
import ftbsc.lll.proxies.impl.FieldProxy;
|
||||||
import org.objectweb.asm.tree.FieldInsnNode;
|
import org.objectweb.asm.tree.FieldInsnNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,11 +17,6 @@ public class FieldProxyInsnNode extends FieldInsnNode {
|
||||||
* @param f a {@link FieldProxy} representing the field to call
|
* @param f a {@link FieldProxy} representing the field to call
|
||||||
*/
|
*/
|
||||||
public FieldProxyInsnNode(int opcode, FieldProxy f) {
|
public FieldProxyInsnNode(int opcode, FieldProxy f) {
|
||||||
super(
|
super(opcode, f.parent.internalName, f.name, f.descriptor);
|
||||||
opcode,
|
|
||||||
f.getParent().replace('.', '/'),
|
|
||||||
f.getName(),
|
|
||||||
f.getDescriptor()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package ftbsc.lll.tools.nodes;
|
package ftbsc.lll.tools.nodes;
|
||||||
|
|
||||||
import ftbsc.lll.proxies.MethodProxy;
|
import ftbsc.lll.proxies.impl.MethodProxy;
|
||||||
import org.objectweb.asm.tree.MethodInsnNode;
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,11 +18,6 @@ public class MethodProxyInsnNode extends MethodInsnNode {
|
||||||
* @param m a {@link MethodProxy} representing the method to call
|
* @param m a {@link MethodProxy} representing the method to call
|
||||||
*/
|
*/
|
||||||
public MethodProxyInsnNode(int opcode, MethodProxy m) {
|
public MethodProxyInsnNode(int opcode, MethodProxy m) {
|
||||||
super(
|
super(opcode, m.parent.internalName, m.name, m.descriptor);
|
||||||
opcode,
|
|
||||||
m.getParent().replace('.', '/'),
|
|
||||||
m.getName(),
|
|
||||||
m.getDescriptor()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
23
src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java
Normal file
23
src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package ftbsc.lll.tools.nodes;
|
||||||
|
|
||||||
|
import ftbsc.lll.proxies.impl.TypeProxy;
|
||||||
|
import org.objectweb.asm.tree.TypeInsnNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the {@link TypeInsnNode} to add a constructor
|
||||||
|
* taking in a {@link TypeProxy}.
|
||||||
|
* @since 0.4.0
|
||||||
|
*/
|
||||||
|
public class TypeProxyInsnNode extends TypeInsnNode {
|
||||||
|
/**
|
||||||
|
* Constructs a new {@link TypeInsnNode} starting from a
|
||||||
|
* {@link TypeProxy}. The user should ensure that the TypeInsnNode
|
||||||
|
* represents a declared type before calling this.
|
||||||
|
* @param opcode the opcode, must be one of NEW, ANEWARRAY,
|
||||||
|
* CHECKCAST or INSTANCEOF
|
||||||
|
* @param t a {@link TypeProxy} representing the type to call
|
||||||
|
*/
|
||||||
|
public TypeProxyInsnNode(int opcode, TypeProxy t) {
|
||||||
|
super(opcode, t.internalName);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue