Merge remote-tracking branch 'bfbc/avian-pack'

Conflicts:
	makefile
This commit is contained in:
Joel Dice
2014-10-08 14:04:00 -06:00
5 changed files with 257 additions and 24 deletions

View File

@ -28,12 +28,15 @@ import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.SignatureParser;
import java.lang.annotation.Annotation;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;
import java.security.ProtectionDomain;
@ -53,7 +56,11 @@ public final class Class <T>
}
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,
@ -505,6 +512,51 @@ public final class Class <T>
public Class getSuperclass() {
return (vmClass.super_ == null ? null : SystemClassLoader.getClass(vmClass.super_));
}
private enum ClassType { GLOBAL, MEMBER, LOCAL, ANONYMOUS }
/**
* Determines the class type.
*
* There are four class types: global (no dollar sign), anonymous (only digits after the dollar sign),
* local (starts with digits after the dollar, ends in class name) and member (does not start with digits
* after the dollar sign).
*
* @return the class type
*/
private ClassType getClassType() {
final String name = getName();
// Find the last dollar, as classes can be nested
int dollar = name.lastIndexOf('$');
if (dollar < 0) return ClassType.GLOBAL;
// Find the first non-digit after the dollar, if any
final char[] chars = name.toCharArray();
int skipDigits;
for (skipDigits = dollar + 1; skipDigits < chars.length; skipDigits++) {
if (chars[skipDigits] < '0' || chars[skipDigits] > '9') break;
}
if (skipDigits == chars.length) {
return ClassType.ANONYMOUS;
} else if (skipDigits > dollar + 1) {
return ClassType.MEMBER;
} else {
return ClassType.LOCAL;
}
}
public boolean isAnonymousClass () {
return getClassType() == ClassType.ANONYMOUS;
}
public boolean isLocalClass () {
return getClassType() == ClassType.LOCAL;
}
public boolean isMemberClass () {
return getClassType() == ClassType.MEMBER;
}
public boolean isArray() {
return vmClass.arrayDimensions != 0;
@ -661,6 +713,53 @@ public final class Class <T>
}
public Type[] getGenericInterfaces() {
throw new UnsupportedOperationException("not yet implemented");
if (vmClass.addendum == null || vmClass.addendum.signature == null) {
return getInterfaces();
}
String signature = Classes.toString((byte[]) vmClass.addendum.signature);
final char[] signChars = signature.toCharArray();
// Addendum format:
// <generic args if present>LBaseClass;LIface1;LIface2;...
// We should split it
int i = -1;
// Passing the generic args
int angles = 0;
do {
i++;
if (signChars[i] == '<') angles ++;
else if (signChars[i] == '>') angles --;
} while (angles > 0);
if (signChars[i] == '>') i++;
// Splitting types list
LinkedList<String> typeSigns = new LinkedList<String>();
StringBuilder curTypeSign = new StringBuilder();
for (; i < signChars.length; i++) {
// Counting braces
if (signChars[i] == '<') angles ++;
else if (signChars[i] == '>') angles --;
// Appending character
curTypeSign.append(signChars[i]);
// Splitting
if (angles == 0 && signChars[i] == ';') {
typeSigns.add(curTypeSign.toString());
curTypeSign.setLength(0);
}
}
if (curTypeSign.length() > 0) typeSigns.add(curTypeSign.toString());
// Parsing types, ignoring the first item in the array
// cause it's the base type
Type[] res = new Type[typeSigns.size() - 1];
for (i = 0; i < typeSigns.size() - 1; i++) {
res[i] = SignatureParser.parse(vmClass.loader, typeSigns.get(i + 1), this);
}
return res;
}
}