mirror of
https://github.com/corda/corda.git
synced 2025-06-14 13:18:18 +00:00
Reflection improved
This commit is contained in:
@ -34,6 +34,7 @@ import java.io.InputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -55,7 +56,11 @@ public final class Class <T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getName();
|
String res;
|
||||||
|
if (isInterface()) res = "interface ";
|
||||||
|
else if (isAnnotation()) res = "annotation ";
|
||||||
|
else res = "class ";
|
||||||
|
return res + getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] replace(int a, int b, byte[] s, int offset,
|
private static byte[] replace(int a, int b, byte[] s, int offset,
|
||||||
@ -710,7 +715,7 @@ public final class Class <T>
|
|||||||
|
|
||||||
public Type[] getGenericInterfaces() {
|
public Type[] getGenericInterfaces() {
|
||||||
if (vmClass.addendum == null || vmClass.addendum.signature == null) {
|
if (vmClass.addendum == null || vmClass.addendum.signature == null) {
|
||||||
return new Type[] {};
|
return getInterfaces();
|
||||||
}
|
}
|
||||||
String signature = Classes.toString((byte[]) vmClass.addendum.signature);
|
String signature = Classes.toString((byte[]) vmClass.addendum.signature);
|
||||||
final char[] signChars = signature.toCharArray();
|
final char[] signChars = signature.toCharArray();
|
||||||
@ -753,13 +758,9 @@ public final class Class <T>
|
|||||||
// cause it's the base type
|
// cause it's the base type
|
||||||
Type[] res = new Type[typeSigns.size() - 1];
|
Type[] res = new Type[typeSigns.size() - 1];
|
||||||
for (i = 0; i < typeSigns.size() - 1; i++) {
|
for (i = 0; i < typeSigns.size() - 1; i++) {
|
||||||
res[i] = SignatureParser.parse(vmClass.loader, typeSigns.get(i + 1));
|
res[i] = SignatureParser.parse(vmClass.loader, typeSigns.get(i + 1), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
/* String signature = Classes.toString((byte[]) vmField.addendum.signature);
|
|
||||||
return SignatureParser.parse(vmClass.loader, signature);*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ public class Field<T> extends AccessibleObject {
|
|||||||
return getType();
|
return getType();
|
||||||
}
|
}
|
||||||
String signature = Classes.toString((byte[]) vmField.addendum.signature);
|
String signature = Classes.toString((byte[]) vmField.addendum.signature);
|
||||||
return SignatureParser.parse(vmField.class_.loader, signature);
|
return SignatureParser.parse(vmField.class_.loader, signature, getDeclaringClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(Object instance) throws IllegalAccessException {
|
public Object get(Object instance) throws IllegalAccessException {
|
||||||
|
@ -10,22 +10,33 @@
|
|||||||
|
|
||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
import avian.Classes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class SignatureParser {
|
public class SignatureParser {
|
||||||
private final ClassLoader loader;
|
private final ClassLoader loader;
|
||||||
private final char[] array;
|
private final char[] array;
|
||||||
private int offset;
|
private int offset;
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
private final Map<String, TypeVariable> typeVariables;
|
||||||
|
|
||||||
public static Type parse(ClassLoader loader, String signature) {
|
public static Type parse(ClassLoader loader, String signature, Class declaringClass) {
|
||||||
return new SignatureParser(loader, signature).type;
|
return new SignatureParser(loader, signature, collectTypeVariables(declaringClass)).type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SignatureParser(ClassLoader loader, String signature) {
|
private static Type parse(ClassLoader loader, String signature, Map<String, TypeVariable> typeVariables) {
|
||||||
|
return new SignatureParser(loader, signature, typeVariables).type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SignatureParser(ClassLoader loader, String signature, Map<String, TypeVariable> typeVariables) {
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
array = signature.toCharArray();
|
array = signature.toCharArray();
|
||||||
|
this.typeVariables = typeVariables;
|
||||||
type = parseType();
|
type = parseType();
|
||||||
if (offset != array.length) {
|
if (offset != array.length) {
|
||||||
throw new IllegalArgumentException("Extra characters after " + offset
|
throw new IllegalArgumentException("Extra characters after " + offset
|
||||||
@ -51,6 +62,12 @@ public class SignatureParser {
|
|||||||
return Short.TYPE;
|
return Short.TYPE;
|
||||||
} else if (c == 'Z') {
|
} else if (c == 'Z') {
|
||||||
return Boolean.TYPE;
|
return Boolean.TYPE;
|
||||||
|
} else if (c == 'T') {
|
||||||
|
StringBuilder tnsb = new StringBuilder();
|
||||||
|
while ((c = array[offset++]) != ';') {
|
||||||
|
tnsb.append(c);
|
||||||
|
}
|
||||||
|
return typeVariables.get(tnsb.toString());
|
||||||
} else if (c != 'L') {
|
} else if (c != 'L') {
|
||||||
throw new IllegalArgumentException("Unexpected character: " + c);
|
throw new IllegalArgumentException("Unexpected character: " + c);
|
||||||
}
|
}
|
||||||
@ -73,7 +90,7 @@ public class SignatureParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lastDollar = rawTypeName.lastIndexOf('$');
|
int lastDollar = rawTypeName.lastIndexOf('$');
|
||||||
if (lastDollar != -1) {
|
if (lastDollar != -1 && ownerType == null) {
|
||||||
String ownerName = rawTypeName.substring(0, lastDollar);
|
String ownerName = rawTypeName.substring(0, lastDollar);
|
||||||
try {
|
try {
|
||||||
ownerType = loader.loadClass(ownerName);
|
ownerType = loader.loadClass(ownerName);
|
||||||
@ -143,4 +160,95 @@ public class SignatureParser {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String, TypeVariable> collectTypeVariables(Class clz) {
|
||||||
|
Map<String, TypeVariable> varsMap = new HashMap<String, TypeVariable>();
|
||||||
|
LinkedList<Class> classList = new LinkedList<Class>();
|
||||||
|
for (Class c = clz; c != null; c = c.getDeclaringClass()) {
|
||||||
|
classList.addFirst(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Class cur : classList) {
|
||||||
|
final List<TypeVariable> varsList = new LinkedList<TypeVariable>();
|
||||||
|
if (cur.vmClass.addendum != null && cur.vmClass.addendum.signature != null) {
|
||||||
|
String signature = Classes.toString((byte[]) cur.vmClass.addendum.signature);
|
||||||
|
final char[] signChars = signature.toCharArray();
|
||||||
|
int i = 0;
|
||||||
|
if (signChars[i] == '<') {
|
||||||
|
i++;
|
||||||
|
do {
|
||||||
|
StringBuilder typeVarSB = new StringBuilder();
|
||||||
|
while (signChars[i] != ':') {
|
||||||
|
typeVarSB.append(signChars[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
String typeVarName = typeVarSB.toString();
|
||||||
|
i++;
|
||||||
|
|
||||||
|
StringBuilder typeSB = new StringBuilder();
|
||||||
|
|
||||||
|
int angles = 0;
|
||||||
|
while (angles > 0 || signChars[i] != ';') {
|
||||||
|
if (signChars[i] == '<') angles ++;
|
||||||
|
else if (signChars[i] == '>') angles --;
|
||||||
|
typeSB.append(signChars[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
typeSB.append(signChars[i]);
|
||||||
|
String typeName = typeSB.toString();
|
||||||
|
final Type baseType = SignatureParser.parse(cur.vmClass.loader, typeName, varsMap);
|
||||||
|
|
||||||
|
TypeVariable tv = new TypeVariableImpl(typeVarName, baseType);
|
||||||
|
varsList.add(tv);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
} while (signChars[i] != '>');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (TypeVariable tv : varsList) {
|
||||||
|
((TypeVariableImpl)tv).setVars(varsList);
|
||||||
|
varsMap.put(tv.getName(), tv);
|
||||||
|
}
|
||||||
|
cur = cur.getDeclaringClass();
|
||||||
|
};
|
||||||
|
return varsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TypeVariableImpl implements TypeVariable {
|
||||||
|
private String name;
|
||||||
|
private Type baseType;
|
||||||
|
private TypeVariable[] vars;
|
||||||
|
|
||||||
|
public Type[] getBounds() {
|
||||||
|
return new Type[] { baseType };
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenericDeclaration getGenericDeclaration() {
|
||||||
|
return new GenericDeclaration() {
|
||||||
|
public TypeVariable<?>[] getTypeParameters() {
|
||||||
|
return vars;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeVariableImpl(String name, Type baseType) {
|
||||||
|
this.name = name;
|
||||||
|
this.baseType = baseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVars(List<TypeVariable> vars) {
|
||||||
|
this.vars = new TypeVariable[vars.size()];
|
||||||
|
vars.toArray(this.vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
public interface TypeVariable<T extends GenericDeclaration> extends Type {
|
public interface TypeVariable<D extends GenericDeclaration> extends Type {
|
||||||
|
Type[] getBounds();
|
||||||
|
D getGenericDeclaration();
|
||||||
|
String getName();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user