Archiviert
13
0

Moving accessor methods to a separate "Accessors" factory class.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2013-12-09 12:03:30 +01:00
Ursprung b70c7fa775
Commit 143ed2ff02
18 geänderte Dateien mit 430 neuen und 231 gelöschten Zeilen

Datei anzeigen

@ -36,8 +36,9 @@ import com.comphenix.protocol.injector.server.SocketInjector;
import com.comphenix.protocol.injector.server.TemporaryPlayerFactory; import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.VolatileField; import com.comphenix.protocol.reflect.VolatileField;
import com.comphenix.protocol.reflect.FuzzyReflection.FieldAccessor; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.FuzzyReflection.MethodAccessor; import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.utility.MinecraftFields; import com.comphenix.protocol.utility.MinecraftFields;
import com.comphenix.protocol.utility.MinecraftMethods; import com.comphenix.protocol.utility.MinecraftMethods;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
@ -213,10 +214,10 @@ class ChannelInjector extends ByteToMessageDecoder {
patchEncoder(vanillaEncoder); patchEncoder(vanillaEncoder);
if (DECODE_BUFFER == null) if (DECODE_BUFFER == null)
DECODE_BUFFER = FuzzyReflection.getMethodAccessor(vanillaDecoder.getClass(), DECODE_BUFFER = Accessors.getMethodAccessor(vanillaDecoder.getClass(),
"decode", ChannelHandlerContext.class, ByteBuf.class, List.class); "decode", ChannelHandlerContext.class, ByteBuf.class, List.class);
if (ENCODE_BUFFER == null) if (ENCODE_BUFFER == null)
ENCODE_BUFFER = FuzzyReflection.getMethodAccessor(vanillaEncoder.getClass(), ENCODE_BUFFER = Accessors.getMethodAccessor(vanillaEncoder.getClass(),
"encode", ChannelHandlerContext.class, Object.class, ByteBuf.class); "encode", ChannelHandlerContext.class, Object.class, ByteBuf.class);
// Intercept sent packets // Intercept sent packets
@ -265,7 +266,7 @@ class ChannelInjector extends ByteToMessageDecoder {
*/ */
private void patchEncoder(MessageToByteEncoder<Object> encoder) { private void patchEncoder(MessageToByteEncoder<Object> encoder) {
if (ENCODER_TYPE_MATCHER == null) { if (ENCODER_TYPE_MATCHER == null) {
ENCODER_TYPE_MATCHER = FuzzyReflection.getFieldAccessor(encoder.getClass(), "matcher", true); ENCODER_TYPE_MATCHER = Accessors.getFieldAccessor(encoder.getClass(), "matcher", true);
} }
ENCODER_TYPE_MATCHER.set(encoder, TypeParameterMatcher.get(MinecraftReflection.getPacketClass())); ENCODER_TYPE_MATCHER.set(encoder, TypeParameterMatcher.get(MinecraftReflection.getPacketClass()));
} }
@ -490,7 +491,7 @@ class ChannelInjector extends ByteToMessageDecoder {
*/ */
public Protocol getCurrentProtocol() { public Protocol getCurrentProtocol() {
if (PROTOCOL_ACCESSOR == null) { if (PROTOCOL_ACCESSOR == null) {
PROTOCOL_ACCESSOR = FuzzyReflection.getFieldAccessor( PROTOCOL_ACCESSOR = Accessors.getFieldAccessor(
networkManager.getClass(), MinecraftReflection.getEnumProtocolClass(), true); networkManager.getClass(), MinecraftReflection.getEnumProtocolClass(), true);
} }
return Protocol.fromVanilla((Enum<?>) PROTOCOL_ACCESSOR.get(networkManager)); return Protocol.fromVanilla((Enum<?>) PROTOCOL_ACCESSOR.get(networkManager));

Datei anzeigen

@ -5,8 +5,8 @@ import java.net.SocketAddress;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.FuzzyReflection.FieldAccessor; import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.minecraft.util.io.netty.buffer.ByteBufAllocator; import net.minecraft.util.io.netty.buffer.ByteBufAllocator;
@ -128,7 +128,7 @@ abstract class ChannelProxy implements Channel {
if (accessor == null) { if (accessor == null) {
try { try {
accessor = FuzzyReflection.getFieldAccessor(clazz, messageClass, true); accessor = Accessors.getFieldAccessor(clazz, messageClass, true);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
accessor = MARK_NO_MESSAGE; accessor = MARK_NO_MESSAGE;
} }

Datei anzeigen

@ -6,7 +6,6 @@ import java.util.List;
import com.comphenix.protocol.reflect.compiler.EmptyClassVisitor; import com.comphenix.protocol.reflect.compiler.EmptyClassVisitor;
import com.comphenix.protocol.reflect.compiler.EmptyMethodVisitor; import com.comphenix.protocol.reflect.compiler.EmptyMethodVisitor;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.sf.cglib.asm.ClassReader; import net.sf.cglib.asm.ClassReader;

Datei anzeigen

@ -0,0 +1,143 @@
package com.comphenix.protocol.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
public class ExactReflection {
// The class we're actually representing
private Class<?> source;
private boolean forceAccess;
private ExactReflection(Class<?> source, boolean forceAccess) {
this.source = Preconditions.checkNotNull(source, "source class cannot be NULL");
this.forceAccess = forceAccess;
}
/**
* Retrieves an exact reflection instance from a given class.
* @param source - the class we'll use.
* @return A fuzzy reflection instance.
*/
public static ExactReflection fromClass(Class<?> source) {
return fromClass(source, false);
}
/**
* Retrieves an exact reflection instance from a given class.
* @param source - the class we'll use.
* @param forceAccess - whether or not to override scope restrictions.
* @return A fuzzy reflection instance.
*/
public static ExactReflection fromClass(Class<?> source, boolean forceAccess) {
return new ExactReflection(source, forceAccess);
}
/**
* Retrieves an exact reflection instance from an object.
* @param reference - the object we'll use.
* @return A fuzzy reflection instance that uses the class of the given object.
*/
public static ExactReflection fromObject(Object reference) {
return new ExactReflection(reference.getClass(), false);
}
/**
* Retrieves an exact reflection instance from an object.
* @param reference - the object we'll use.
* @param forceAccess - whether or not to override scope restrictions.
* @return A fuzzy reflection instance that uses the class of the given object.
*/
public static ExactReflection fromObject(Object reference, boolean forceAccess) {
return new ExactReflection(reference.getClass(), forceAccess);
}
/**
* Retrieve the first method in the class hierachy with the given name and parameters.
* <p>
* If {@link #isForceAccess()} is TRUE, we will also search for protected and private methods.
* @param methodName - the method name to find, or NULL to look for everything.
* @param parameters - the parameters.
* @return The first matched method.
* @throws IllegalArgumentException If we cannot find a method by this name.
*/
public Method getMethod(String methodName, Class<?>... parameters) {
return getMethod(source, methodName, parameters);
}
// For recursion
private Method getMethod(Class<?> instanceClass, String methodName, Class<?>... parameters) {
for (Method method : instanceClass.getDeclaredMethods()) {
if ((forceAccess || Modifier.isPublic(method.getModifiers())) &&
(methodName == null || method.getName().equals(methodName)) &&
Arrays.equals(method.getParameterTypes(), parameters)) {
method.setAccessible(true);
return method;
}
}
// Search in every superclass
if (instanceClass.getSuperclass() != null)
return getMethod(instanceClass.getSuperclass(), methodName, parameters);
throw new IllegalArgumentException(String.format(
"Unable to find method %s (%s) in %s.", methodName, Arrays.asList(parameters), source));
}
/**
* Retrieve a field in the class hierachy by the given name.
* <p>
* If {@link #isForceAccess()} is TRUE, we will also search for protected and private fields.
* @param fieldName - the field name. Cannot be NULL.
* @return The first matched field.
*/
public Field getField(String fieldName) {
return getField(source, fieldName);
}
// For recursion
private Field getField(Class<?> instanceClass, @Nonnull String fieldName) {
// Ignore access rules
for (Field field : instanceClass.getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
field.setAccessible(true);
return field;
}
}
// Recursively fild the correct field
if (instanceClass.getSuperclass() != null)
return getField(instanceClass.getSuperclass(), fieldName);
throw new IllegalArgumentException(String.format(
"Unable to find field %s in %s.", fieldName, source));
}
/**
* Retrieve an {@link ExactReflection} object where scope restrictions are ignored.
* @return A copy of the current object.
*/
public ExactReflection forceAccess() {
return new ExactReflection(source, true);
}
/**
* Determine if we are overriding scope restrictions and will also find
* private, protected or package members.
* @return TRUE if we are, FALSE otherwise.
*/
public boolean isForceAccess() {
return forceAccess;
}
/**
* Retrieve the source class we are searching.
* @return The source.
*/
public Class<?> getSource() {
return source;
}
}

Datei anzeigen

@ -29,9 +29,9 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher; import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -42,85 +42,6 @@ import com.google.common.collect.Sets;
* @author Kristian * @author Kristian
*/ */
public class FuzzyReflection { public class FuzzyReflection {
/**
* Represents an interface for accessing a field.
* @author Kristian
*/
public interface FieldAccessor {
/**
* Retrieve the value of a field for a particular instance.
* @param instance - the instance, or NULL for a static field.
* @return The value of the field.
* @throws IllegalStateException If the current security context prohibits reflection.
*/
public Object get(Object instance);
/**
* Set the value of a field for a particular instance.
* @param instance - the instance, or NULL for a static field.
* @param value - the new value of the field.
*/
public void set(Object instance, Object value);
/**
* Retrieve the underlying field.
* @return The field.
*/
public Field getField();
}
/**
* Represents an interface for invoking a method.
* @author Kristian
*/
public interface MethodAccessor {
/**
* Invoke the underlying method.
* @param target - the target instance, or NULL for a static method.
* @param args - the arguments to pass to the method.
* @return The return value, or NULL for void methods.
*/
public Object invoke(Object target, Object... args);
/**
* Retrieve the underlying method.
* @return The method.
*/
public Method getMethod();
}
/**
* Represents a field accessor that synchronizes access to the underlying field.
* @author Kristian
*/
private static final class SynchronizedFieldAccessor implements FieldAccessor {
private final FieldAccessor accessor;
private SynchronizedFieldAccessor(FieldAccessor accessor) {
this.accessor = accessor;
}
@Override
public void set(Object instance, Object value) {
Object lock = accessor.get(instance);
if (lock != null) {
synchronized (lock) {
accessor.set(instance, value);
}
} else {
accessor.set(instance, value);
}
}
@Override
public Object get(Object instance) {
return accessor.get(instance);
}
@Override
public Field getField() {
return accessor.getField();
}
}
// The class we're actually representing // The class we're actually representing
private Class<?> source; private Class<?> source;
@ -170,107 +91,6 @@ public class FuzzyReflection {
return new FuzzyReflection(reference.getClass(), forceAccess); return new FuzzyReflection(reference.getClass(), forceAccess);
} }
/**
* Retrieve an accessor for the first field of the given type.
* @param instanceClass - the type of the instance to retrieve.
* @param fieldClass - type of the field to retrieve.
* @param forceAccess - whether or not to look for private and protected fields.
* @return The value of that field.
* @throws IllegalArgumentException If the field cannot be found.
*/
public static FieldAccessor getFieldAccessor(Class<?> instanceClass, Class<?> fieldClass, boolean forceAccess) {
// Get a field accessor
Field field = FuzzyReflection.fromClass(instanceClass, forceAccess).getFieldByType(null, fieldClass);
return getFieldAccessor(field);
}
/**
* Retrieve an accessor for the first field of the given type.
* @param instanceClass - the type of the instance to retrieve.
* @param fieldClass - type of the field to retrieve.
* @param forceAccess - whether or not to look for private and protected fields.
* @return The value of that field.
* @throws IllegalArgumentException If the field cannot be found.
*/
public static FieldAccessor getFieldAccessor(Class<?> instanceClass, String fieldName, boolean forceAccess) {
return getFieldAccessor(FieldUtils.getField(instanceClass, fieldName, forceAccess));
}
/**
* Retrieve a field accessor from a given field that uses unchecked exceptions.
* @param field - the field.
* @return The field accessor.
*/
public static FieldAccessor getFieldAccessor(final Field field) {
return getFieldAccessor(field, true);
}
/**
* Retrieve a field accessor from a given field that uses unchecked exceptions.
* @param field - the field.
* @param forceAccess - whether or not to skip Java access checking.
* @return The field accessor.
*/
public static FieldAccessor getFieldAccessor(final Field field, boolean forceAccess) {
field.setAccessible(true);
return new DefaultFieldAccessor(field);
}
/**
* Retrieve a field accessor where the write operation is synchronized on the current field value.
* @param accessor - the accessor.
* @return The field accessor.
*/
public static FieldAccessor getSynchronized(final FieldAccessor accessor) {
// Only wrap once
if (accessor instanceof SynchronizedFieldAccessor)
return accessor;
return new SynchronizedFieldAccessor(accessor);
}
/**
* Retrieve a method accessor for a method with the given name and signature.
* @param instanceClass - the parent class.
* @param name - the method name.
* @param parameters - the parameters.
* @return The method accessor.
*/
public static MethodAccessor getMethodAccessor(Class<?> instanceClass, String name, Class<?>... parameters) {
return getMethodAccessor(instanceClass, instanceClass, name, parameters);
}
// Helper method
private static MethodAccessor getMethodAccessor(
Class<?> initialClass, Class<?> instanceClass, String name, Class<?>... parameters) {
try {
Method method = instanceClass.getDeclaredMethod(name, parameters);
method.setAccessible(true);
return getMethodAccessor(method);
} catch (NoSuchMethodException e) {
// Search for a private method in the superclass
if (initialClass.getSuperclass() != null)
return getMethodAccessor(initialClass, instanceClass.getSuperclass(), name, parameters);
// Unable to find it
throw new IllegalArgumentException("Unable to find method " + name +
"(" + Joiner.on(", ").join(parameters) +") in " + initialClass);
} catch (Exception e) {
throw new RuntimeException("Unable to retrieve methods.", e);
}
}
/**
* Retrieve a method accessor for a particular method, avoding checked exceptions.
* @param method - the method to access.
* @return The method accessor.
*/
public static MethodAccessor getMethodAccessor(final Method method) {
return new DefaultMethodAccessor(method);
}
/** /**
* Retrieve the value of the first field of the given type. * Retrieve the value of the first field of the given type.
* @param instance - the instance to retrieve from. * @param instance - the instance to retrieve from.
@ -281,7 +101,7 @@ public class FuzzyReflection {
*/ */
public static <T> T getFieldValue(Object instance, Class<T> fieldClass, boolean forceAccess) { public static <T> T getFieldValue(Object instance, Class<T> fieldClass, boolean forceAccess) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
T result = (T) getFieldAccessor(instance.getClass(), fieldClass, forceAccess).get(instance); T result = (T) Accessors.getFieldAccessor(instance.getClass(), fieldClass, forceAccess).get(instance);
return result; return result;
} }

Datei anzeigen

@ -19,7 +19,8 @@ package com.comphenix.protocol.reflect;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import com.comphenix.protocol.reflect.FuzzyReflection.FieldAccessor; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.google.common.base.Objects; import com.google.common.base.Objects;
/** /**
@ -48,7 +49,7 @@ public class VolatileField {
* @param container - the object this field belongs to. * @param container - the object this field belongs to.
*/ */
public VolatileField(Field field, Object container) { public VolatileField(Field field, Object container) {
this.accessor = FuzzyReflection.getFieldAccessor(field); this.accessor = Accessors.getFieldAccessor(field);
this.container = container; this.container = container;
} }
@ -59,7 +60,7 @@ public class VolatileField {
* @param forceAccess - whether or not to override any scope restrictions. * @param forceAccess - whether or not to override any scope restrictions.
*/ */
public VolatileField(Field field, Object container, boolean forceAccess) { public VolatileField(Field field, Object container, boolean forceAccess) {
this.accessor = FuzzyReflection.getFieldAccessor(field, true); this.accessor = Accessors.getFieldAccessor(field, true);
this.container = container; this.container = container;
this.forceAccess = forceAccess; this.forceAccess = forceAccess;
} }
@ -193,7 +194,7 @@ public class VolatileField {
* @return A synchronized volatile field. * @return A synchronized volatile field.
*/ */
public VolatileField toSynchronized() { public VolatileField toSynchronized() {
return new VolatileField(FuzzyReflection.getSynchronized(accessor), container); return new VolatileField(Accessors.getSynchronized(accessor), container);
} }
/** /**

Datei anzeigen

@ -0,0 +1,125 @@
package com.comphenix.protocol.reflect.accessors;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.comphenix.protocol.reflect.ExactReflection;
import com.comphenix.protocol.reflect.FuzzyReflection;
public final class Accessors {
/**
* Represents a field accessor that synchronizes access to the underlying field.
* @author Kristian
*/
public static final class SynchronizedFieldAccessor implements FieldAccessor {
private final FieldAccessor accessor;
private SynchronizedFieldAccessor(FieldAccessor accessor) {
this.accessor = accessor;
}
@Override
public void set(Object instance, Object value) {
Object lock = accessor.get(instance);
if (lock != null) {
synchronized (lock) {
accessor.set(instance, value);
}
} else {
accessor.set(instance, value);
}
}
@Override
public Object get(Object instance) {
return accessor.get(instance);
}
@Override
public Field getField() {
return accessor.getField();
}
}
/**
* Retrieve an accessor for the first field of the given type.
* @param instanceClass - the type of the instance to retrieve.
* @param fieldClass - type of the field to retrieve.
* @param forceAccess - whether or not to look for private and protected fields.
* @return The value of that field.
* @throws IllegalArgumentException If the field cannot be found.
*/
public static FieldAccessor getFieldAccessor(Class<?> instanceClass, Class<?> fieldClass, boolean forceAccess) {
// Get a field accessor
Field field = FuzzyReflection.fromClass(instanceClass, forceAccess).getFieldByType(null, fieldClass);
return Accessors.getFieldAccessor(field);
}
/**
* Retrieve an accessor for the first field of the given type.
* @param instanceClass - the type of the instance to retrieve.
* @param fieldClass - type of the field to retrieve.
* @param forceAccess - whether or not to look for private and protected fields.
* @return The value of that field.
* @throws IllegalArgumentException If the field cannot be found.
*/
public static FieldAccessor getFieldAccessor(Class<?> instanceClass, String fieldName, boolean forceAccess) {
return Accessors.getFieldAccessor(ExactReflection.fromClass(instanceClass, true).getField(fieldName));
}
/**
* Retrieve a field accessor from a given field that uses unchecked exceptions.
* @param field - the field.
* @return The field accessor.
*/
public static FieldAccessor getFieldAccessor(final Field field) {
return Accessors.getFieldAccessor(field, true);
}
/**
* Retrieve a field accessor from a given field that uses unchecked exceptions.
* @param field - the field.
* @param forceAccess - whether or not to skip Java access checking.
* @return The field accessor.
*/
public static FieldAccessor getFieldAccessor(final Field field, boolean forceAccess) {
field.setAccessible(true);
return new DefaultFieldAccessor(field);
}
/**
* Retrieve a field accessor where the write operation is synchronized on the current field value.
* @param accessor - the accessor.
* @return The field accessor.
*/
public static FieldAccessor getSynchronized(final FieldAccessor accessor) {
// Only wrap once
if (accessor instanceof SynchronizedFieldAccessor)
return accessor;
return new SynchronizedFieldAccessor(accessor);
}
/**
* Retrieve a method accessor for a method with the given name and signature.
* @param instanceClass - the parent class.
* @param methodName - the method name.
* @param parameters - the parameters.
* @return The method accessor.
*/
public static MethodAccessor getMethodAccessor(Class<?> instanceClass, String methodName, Class<?>... parameters) {
return new DefaultMethodAccessor(ExactReflection.fromClass(instanceClass, true).getMethod(methodName, parameters));
}
/**
* Retrieve a method accessor for a particular method, avoding checked exceptions.
* @param method - the method to access.
* @return The method accessor.
*/
public static MethodAccessor getMethodAccessor(final Method method) {
return new DefaultMethodAccessor(method);
}
// Seal this class
private Accessors() {
}
}

Datei anzeigen

@ -1,9 +1,7 @@
package com.comphenix.protocol.reflect; package com.comphenix.protocol.reflect.accessors;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import com.comphenix.protocol.reflect.FuzzyReflection.FieldAccessor;
final class DefaultFieldAccessor implements FieldAccessor { final class DefaultFieldAccessor implements FieldAccessor {
private final Field field; private final Field field;

Datei anzeigen

@ -1,10 +1,8 @@
package com.comphenix.protocol.reflect; package com.comphenix.protocol.reflect.accessors;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import com.comphenix.protocol.reflect.FuzzyReflection.MethodAccessor;
final class DefaultMethodAccessor implements MethodAccessor { final class DefaultMethodAccessor implements MethodAccessor {
private final Method method; private final Method method;

Datei anzeigen

@ -0,0 +1,30 @@
package com.comphenix.protocol.reflect.accessors;
import java.lang.reflect.Field;
/**
* Represents an interface for accessing a field.
* @author Kristian
*/
public interface FieldAccessor {
/**
* Retrieve the value of a field for a particular instance.
* @param instance - the instance, or NULL for a static field.
* @return The value of the field.
* @throws IllegalStateException If the current security context prohibits reflection.
*/
public Object get(Object instance);
/**
* Set the value of a field for a particular instance.
* @param instance - the instance, or NULL for a static field.
* @param value - the new value of the field.
*/
public void set(Object instance, Object value);
/**
* Retrieve the underlying field.
* @return The field.
*/
public Field getField();
}

Datei anzeigen

@ -0,0 +1,23 @@
package com.comphenix.protocol.reflect.accessors;
import java.lang.reflect.Method;
/**
* Represents an interface for invoking a method.
* @author Kristian
*/
public interface MethodAccessor {
/**
* Invoke the underlying method.
* @param target - the target instance, or NULL for a static method.
* @param args - the arguments to pass to the method.
* @return The return value, or NULL for void methods.
*/
public Object invoke(Object target, Object... args);
/**
* Retrieve the underlying method.
* @return The method.
*/
public Method getMethod();
}

Datei anzeigen

@ -12,8 +12,8 @@ import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel; import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.WritableByteChannel; import java.nio.channels.WritableByteChannel;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.FuzzyReflection.FieldAccessor; import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.LimitInputStream; import com.google.common.io.LimitInputStream;
@ -47,10 +47,10 @@ class ByteBufAdapter extends AbstractByteBuf {
// Prepare accessors // Prepare accessors
try { try {
if (READER_INDEX == null) { if (READER_INDEX == null) {
READER_INDEX = FuzzyReflection.getFieldAccessor(AbstractByteBuf.class.getDeclaredField("readerIndex")); READER_INDEX = Accessors.getFieldAccessor(AbstractByteBuf.class.getDeclaredField("readerIndex"));
} }
if (WRITER_INDEX == null) { if (WRITER_INDEX == null) {
WRITER_INDEX = FuzzyReflection.getFieldAccessor(AbstractByteBuf.class.getDeclaredField("writerIndex")); WRITER_INDEX = Accessors.getFieldAccessor(AbstractByteBuf.class.getDeclaredField("writerIndex"));
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Cannot initialize ByteBufAdapter.", e); throw new RuntimeException("Cannot initialize ByteBufAdapter.", e);

Datei anzeigen

@ -33,7 +33,8 @@ import com.comphenix.protocol.injector.PacketConstructor;
import com.comphenix.protocol.injector.packet.PacketRegistry; import com.comphenix.protocol.injector.packet.PacketRegistry;
import com.comphenix.protocol.reflect.FieldAccessException; import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.FuzzyReflection.MethodAccessor; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers; import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.google.common.base.Strings; import com.google.common.base.Strings;
@ -108,10 +109,10 @@ public class ChatExtensions {
// Try one of the string constructors // Try one of the string constructors
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
messageFactory = FuzzyReflection.getMethodAccessor( messageFactory = Accessors.getMethodAccessor(
MinecraftReflection.getCraftMessageClass(), "fromString", String.class); MinecraftReflection.getCraftMessageClass(), "fromString", String.class);
} else { } else {
messageFactory = FuzzyReflection.getMethodAccessor( messageFactory = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(messageClass).getMethod( FuzzyReflection.fromClass(messageClass).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
requireModifier(Modifier.STATIC). requireModifier(Modifier.STATIC).

Datei anzeigen

@ -3,8 +3,8 @@ package com.comphenix.protocol.utility;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import com.comphenix.protocol.injector.BukkitUnwrapper; import com.comphenix.protocol.injector.BukkitUnwrapper;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.FuzzyReflection.FieldAccessor; import com.comphenix.protocol.reflect.accessors.FieldAccessor;
/** /**
* Retrieve the content of well-known fields in Minecraft. * Retrieve the content of well-known fields in Minecraft.
@ -30,7 +30,7 @@ public class MinecraftFields {
if (NETWORK_ACCESSOR == null) { if (NETWORK_ACCESSOR == null) {
Class<?> networkClass = MinecraftReflection.getNetworkManagerClass(); Class<?> networkClass = MinecraftReflection.getNetworkManagerClass();
Class<?> connectionClass = MinecraftReflection.getNetServerHandlerClass(); Class<?> connectionClass = MinecraftReflection.getNetServerHandlerClass();
NETWORK_ACCESSOR = FuzzyReflection.getFieldAccessor(connectionClass, networkClass, true); NETWORK_ACCESSOR = Accessors.getFieldAccessor(connectionClass, networkClass, true);
} }
// Retrieve the network manager // Retrieve the network manager
return NETWORK_ACCESSOR.get(getPlayerConnection(nmsPlayer)); return NETWORK_ACCESSOR.get(getPlayerConnection(nmsPlayer));
@ -49,7 +49,7 @@ public class MinecraftFields {
private static Object getPlayerConnection(Object nmsPlayer) { private static Object getPlayerConnection(Object nmsPlayer) {
if (CONNECTION_ACCESSOR == null) { if (CONNECTION_ACCESSOR == null) {
Class<?> connectionClass = MinecraftReflection.getNetServerHandlerClass(); Class<?> connectionClass = MinecraftReflection.getNetServerHandlerClass();
CONNECTION_ACCESSOR = FuzzyReflection.getFieldAccessor(nmsPlayer.getClass(), connectionClass, true); CONNECTION_ACCESSOR = Accessors.getFieldAccessor(nmsPlayer.getClass(), connectionClass, true);
} }
return CONNECTION_ACCESSOR.get(nmsPlayer); return CONNECTION_ACCESSOR.get(nmsPlayer);
} }

Datei anzeigen

@ -55,6 +55,7 @@ import com.comphenix.protocol.injector.packet.PacketRegistry;
import com.comphenix.protocol.reflect.ClassAnalyser; import com.comphenix.protocol.reflect.ClassAnalyser;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.ClassAnalyser.AsmMethod; import com.comphenix.protocol.reflect.ClassAnalyser.AsmMethod;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.compiler.EmptyClassVisitor; import com.comphenix.protocol.reflect.compiler.EmptyClassVisitor;
import com.comphenix.protocol.reflect.compiler.EmptyMethodVisitor; import com.comphenix.protocol.reflect.compiler.EmptyMethodVisitor;
import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher; import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher;
@ -654,7 +655,7 @@ public class MinecraftReflection {
return getMinecraftClass("IChatBaseComponent"); return getMinecraftClass("IChatBaseComponent");
} catch (RuntimeException e) { } catch (RuntimeException e) {
return setMinecraftClass("IChatBaseComponent", return setMinecraftClass("IChatBaseComponent",
FuzzyReflection.getMethodAccessor(getCraftChatMessage(), "fromString", String.class). Accessors.getMethodAccessor(getCraftChatMessage(), "fromString", String.class).
getMethod().getReturnType().getComponentType() getMethod().getReturnType().getComponentType()
); );
} }

Datei anzeigen

@ -13,7 +13,8 @@ import org.bukkit.inventory.ItemStack;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.FuzzyReflection.MethodAccessor; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.wrappers.nbt.NbtCompound; import com.comphenix.protocol.wrappers.nbt.NbtCompound;
import com.comphenix.protocol.wrappers.nbt.NbtFactory; import com.comphenix.protocol.wrappers.nbt.NbtFactory;
@ -100,7 +101,7 @@ public class StreamSerializer {
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
if (READ_ITEM_METHOD == null) { if (READ_ITEM_METHOD == null) {
READ_ITEM_METHOD = FuzzyReflection.getMethodAccessor( READ_ITEM_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true). FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
getMethodByParameters("readItemStack", getMethodByParameters("readItemStack",
MinecraftReflection.getItemStackClass(), new Class<?>[0]) MinecraftReflection.getItemStackClass(), new Class<?>[0])
@ -110,7 +111,7 @@ public class StreamSerializer {
} else { } else {
if (READ_ITEM_METHOD == null) { if (READ_ITEM_METHOD == null) {
READ_ITEM_METHOD = FuzzyReflection.getMethodAccessor( READ_ITEM_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod( FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
parameterCount(1). parameterCount(1).
@ -143,7 +144,7 @@ public class StreamSerializer {
// Invoke the correct method // Invoke the correct method
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
if (READ_NBT_METHOD == null) { if (READ_NBT_METHOD == null) {
READ_NBT_METHOD = FuzzyReflection.getMethodAccessor( READ_NBT_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true). FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
getMethodByParameters("readNbtCompound", getMethodByParameters("readNbtCompound",
MinecraftReflection.getNBTCompoundClass(), new Class<?>[0]) MinecraftReflection.getNBTCompoundClass(), new Class<?>[0])
@ -153,7 +154,7 @@ public class StreamSerializer {
} else { } else {
if (READ_NBT_METHOD == null) { if (READ_NBT_METHOD == null) {
READ_NBT_METHOD = FuzzyReflection.getMethodAccessor( READ_NBT_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod( FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
parameterCount(1). parameterCount(1).
@ -196,7 +197,7 @@ public class StreamSerializer {
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
if (READ_STRING_METHOD == null) { if (READ_STRING_METHOD == null) {
READ_STRING_METHOD = FuzzyReflection.getMethodAccessor( READ_STRING_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true). FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
getMethodByParameters("readString", String.class, new Class<?>[] { int.class }) getMethodByParameters("readString", String.class, new Class<?>[] { int.class })
); );
@ -205,7 +206,7 @@ public class StreamSerializer {
} else { } else {
if (READ_STRING_METHOD == null) { if (READ_STRING_METHOD == null) {
READ_STRING_METHOD = FuzzyReflection.getMethodAccessor( READ_STRING_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod( FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
parameterCount(2). parameterCount(2).
@ -254,7 +255,7 @@ public class StreamSerializer {
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
if (WRITE_ITEM_METHOD == null) { if (WRITE_ITEM_METHOD == null) {
WRITE_ITEM_METHOD = FuzzyReflection.getMethodAccessor( WRITE_ITEM_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true). FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass()) getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass())
); );
@ -263,7 +264,7 @@ public class StreamSerializer {
} else { } else {
if (WRITE_ITEM_METHOD == null) if (WRITE_ITEM_METHOD == null)
WRITE_ITEM_METHOD = FuzzyReflection.getMethodAccessor( WRITE_ITEM_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod( FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
parameterCount(2). parameterCount(2).
@ -293,7 +294,7 @@ public class StreamSerializer {
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
if (WRITE_NBT_METHOD == null) { if (WRITE_NBT_METHOD == null) {
WRITE_NBT_METHOD = FuzzyReflection.getMethodAccessor( WRITE_NBT_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true). FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
getMethodByParameters("writeNbtCompound", MinecraftReflection.getNBTCompoundClass()) getMethodByParameters("writeNbtCompound", MinecraftReflection.getNBTCompoundClass())
); );
@ -302,7 +303,7 @@ public class StreamSerializer {
} else { } else {
if (WRITE_NBT_METHOD == null) { if (WRITE_NBT_METHOD == null) {
WRITE_NBT_METHOD = FuzzyReflection.getMethodAccessor( WRITE_NBT_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true).getMethod( FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
parameterCount(2). parameterCount(2).
@ -332,7 +333,7 @@ public class StreamSerializer {
if (MinecraftReflection.isUsingNetty()) { if (MinecraftReflection.isUsingNetty()) {
if (WRITE_STRING_METHOD == null) { if (WRITE_STRING_METHOD == null) {
WRITE_STRING_METHOD = FuzzyReflection.getMethodAccessor( WRITE_STRING_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true). FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
getMethodByParameters("writeString", String.class) getMethodByParameters("writeString", String.class)
); );
@ -341,7 +342,7 @@ public class StreamSerializer {
} else { } else {
if (WRITE_STRING_METHOD == null) { if (WRITE_STRING_METHOD == null) {
WRITE_STRING_METHOD = FuzzyReflection.getMethodAccessor( WRITE_STRING_METHOD = Accessors.getMethodAccessor(
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod( FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
FuzzyMethodContract.newBuilder(). FuzzyMethodContract.newBuilder().
parameterCount(2). parameterCount(2).

Datei anzeigen

@ -3,7 +3,8 @@ package com.comphenix.protocol.wrappers;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.FuzzyReflection.MethodAccessor; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
/** /**
@ -21,13 +22,13 @@ public class WrappedChatComponent {
FuzzyReflection fuzzy = FuzzyReflection.fromClass(SERIALIZER); FuzzyReflection fuzzy = FuzzyReflection.fromClass(SERIALIZER);
// Retrieve the correct methods // Retrieve the correct methods
SERIALIZE_COMPONENT = FuzzyReflection.getMethodAccessor( SERIALIZE_COMPONENT = Accessors.getMethodAccessor(
fuzzy.getMethodByParameters("serialize", String.class, new Class<?>[] { COMPONENT })); fuzzy.getMethodByParameters("serialize", String.class, new Class<?>[] { COMPONENT }));
DESERIALIZE_COMPONENT = FuzzyReflection.getMethodAccessor( DESERIALIZE_COMPONENT = Accessors.getMethodAccessor(
fuzzy.getMethodByParameters("serialize", COMPONENT, new Class<?>[] { String.class })); fuzzy.getMethodByParameters("serialize", COMPONENT, new Class<?>[] { String.class }));
// Get a component from a standard Minecraft message // Get a component from a standard Minecraft message
CONSTRUCT_COMPONENT = FuzzyReflection.getMethodAccessor( CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(
MinecraftReflection.getCraftChatMessage(), "fromString", String.class); MinecraftReflection.getCraftChatMessage(), "fromString", String.class);
} }

Datei anzeigen

@ -0,0 +1,57 @@
package com.comphenix.protocol.reflect.accessors;
import static org.junit.Assert.*;
import org.junit.Test;
public class AccessorsTest {
// --- Some classes we can use for testing ---
private static class Entity {
private int id;
public Entity(int id) {
this.id = id;
}
public int getId() {
return id;
}
@SuppressWarnings("unused")
private void setId(int value) {
this.id = value;
}
}
private static class Player extends Entity {
private String name;
public Player(int id, String name) {
super(id);
this.name = name;
}
public String getName() {
return name;
}
}
// --- Test classes ---
@Test
public void testField() {
Player player = new Player(123, "ABC");
Accessors.getFieldAccessor(player.getClass(), "id", true).set(player, 0);
Accessors.getFieldAccessor(player.getClass(), "name", true).set(player, "MODIFIED");
assertEquals(0, player.getId());
assertEquals("MODIFIED", player.getName());
}
@Test
public void testMethod() {
Player player = new Player(123, "ABC");
Accessors.getMethodAccessor(player.getClass(), "setId", int.class).invoke(player, 0);
assertEquals(0, player.getId());
}
}