Use local copy of latest bndlib code for pre-release testing purposes
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1347815 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java b/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
new file mode 100644
index 0000000..32ae94f
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
@@ -0,0 +1,220 @@
+package aQute.bnd.compatibility;
+
+import java.lang.reflect.*;
+
+public class RuntimeSignatureBuilder {
+ final Scope root;
+
+ public RuntimeSignatureBuilder(Scope root) {
+ this.root = root;
+ }
+
+ static public String identity(Class<?> c) {
+ return Scope.classIdentity(c.getName());
+ }
+
+ static public String identity(Method m) {
+ return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m
+ .getParameterTypes()));
+ }
+
+ static public String identity(Constructor<?> m) {
+ return Scope.constructorIdentity(getDescriptor(void.class, m.getParameterTypes()));
+ }
+
+ static public String identity(Field m) {
+ return Scope.fieldIdentity(m.getName(), getDescriptor(m.getType(), null));
+ }
+
+ static public String getDescriptor(Class<?> base, Class<?>[] parameters) {
+ StringBuilder sb = new StringBuilder();
+ if (parameters != null) {
+ sb.append("(");
+ for (Class<?> parameter : parameters) {
+ sb.append(getDescriptor(parameter));
+ }
+ sb.append(")");
+ }
+ sb.append(getDescriptor(base));
+ return sb.toString();
+ }
+
+ public Scope add(Class<?> c) {
+ Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(),
+ Kind.CLASS, identity(c), c.getGenericSuperclass(), c.getGenericInterfaces(), null);
+
+ for (Field f : c.getDeclaredFields()) {
+ add(local, // declaring scope
+ local, // enclosing
+ f.getModifiers(), // access modifiers
+ null, // fields have no type vars
+ Kind.FIELD, // field
+ identity(f), // the name of the field
+ f.getGenericType(), // the type of the field
+ null, // fields have no parameters
+ null // fields have no exceptions
+ );
+ }
+
+ for (Constructor<?> constr : c.getConstructors()) {
+ add(local, // class scope
+ local, // enclosing
+ constr.getModifiers(), // access modifiers
+ constr.getTypeParameters(), // Type vars
+ Kind.CONSTRUCTOR, // constructor
+ identity(constr), // <init>(type*)
+ void.class, // Always void
+ constr.getGenericParameterTypes(), // parameters types
+ constr.getGenericExceptionTypes() // exception types
+ );
+ }
+
+ for (Method m : c.getDeclaredMethods()) {
+ if (m.getDeclaringClass() != Object.class) {
+ add(local, // class scope
+ local, // enclosing
+ m.getModifiers(), // access modifiers
+ m.getTypeParameters(), Kind.METHOD, // method
+ identity(m), // <name>(type*)return
+ m.getGenericReturnType(), // return type
+ m.getGenericParameterTypes(), // parameter types
+ m.getGenericExceptionTypes() // exception types
+ );
+ }
+ }
+
+ return local;
+ }
+
+ private Scope getEnclosingScope(Class<?> c) {
+ Method m = c.getEnclosingMethod();
+ if (m != null) {
+ Scope s = getGlobalScope(m.getDeclaringClass());
+ return s.getScope(identity(m));
+ }
+// TODO
+// Constructor cnstr = c.getEnclosingConstructor();
+// if (m != null) {
+// Scope s = getGlobalScope(cnstr.getDeclaringClass());
+// return s.getScope(identity(cnstr));
+//
+// }
+ Class<?> enclosingClass = c.getEnclosingClass();
+ if (enclosingClass != null) {
+ return getGlobalScope(enclosingClass);
+ }
+
+ return null;
+ }
+
+ private Scope getGlobalScope(Class<?> c) {
+ if (c == null)
+ return null;
+ String id = identity(c);
+ return root.getScope(id);
+ }
+
+ private Scope add(Scope declaring, Scope enclosing, int modifiers,
+ TypeVariable<?>[] typeVariables, Kind kind, String id, Type mainType,
+ Type[] parameterTypes, Type exceptionTypes[]) {
+
+ Scope scope = declaring.getScope(id);
+ assert scope.access == Access.UNKNOWN;
+ scope.setAccess(Access.modifier(modifiers));
+ scope.setKind(kind);
+ scope.setGenericParameter(convert(typeVariables));
+ scope.setBase(convert(scope,mainType));
+ scope.setParameterTypes(convert(parameterTypes));
+ scope.setExceptionTypes(convert(exceptionTypes));
+ scope.setDeclaring(declaring);
+ scope.setEnclosing(enclosing);
+ return scope;
+ }
+
+ private GenericType convert(Scope source, Type t) {
+ if (t instanceof ParameterizedType) {
+ // C<P..>
+ ParameterizedType pt = (ParameterizedType) t;
+ /*Scope reference =*/ root.getScope(identity((Class<?>)pt.getRawType()));
+ Type args[] = pt.getActualTypeArguments();
+ GenericType[] arguments = new GenericType[args.length];
+ int n = 0;
+ for (Type arg : args)
+ arguments[n++] = convert(source,arg);
+// return new GenericType(reference,null,arguments);
+
+ } else if (t instanceof TypeVariable) {
+// TypeVariable tv = (TypeVariable) t;
+// return new GenericType(source,tv.getName(), null);
+ } else if (t instanceof WildcardType) {
+// WildcardType wc = (WildcardType) t;
+// wc.
+ } else if (t instanceof GenericArrayType) {
+
+ }
+ if (t instanceof Class<?>) {
+// raw = ((Class<?>) t).getName() + ";";
+ } else
+ throw new IllegalArgumentException(t.toString());
+
+ return null;
+ }
+
+ private GenericParameter[] convert(TypeVariable<?> vars[]) {
+ if (vars == null)
+ return null;
+
+ GenericParameter out[] = new GenericParameter[vars.length];
+ for (int i = 0; i < vars.length; i++) {
+ GenericType gss[] = convert(vars[i].getBounds());
+ out[i] = new GenericParameter(vars[i].getName(), gss);
+ }
+ return out;
+ }
+
+ private GenericType[] convert(Type[] parameterTypes) {
+ if (parameterTypes == null || parameterTypes.length == 0)
+ return GenericType.EMPTY;
+
+ GenericType tss[] = new GenericType[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ //tss[i] = new GenericType(parameterTypes[i]);
+ }
+ return tss;
+ }
+
+ private static String getDescriptor(Class<?> c) {
+ StringBuilder sb = new StringBuilder();
+ if (c.isPrimitive()) {
+ if (c == boolean.class)
+ sb.append("Z");
+ else if (c == byte.class)
+ sb.append("Z");
+ else if (c == char.class)
+ sb.append("C");
+ else if (c == short.class)
+ sb.append("S");
+ else if (c == int.class)
+ sb.append("I");
+ else if (c == long.class)
+ sb.append("J");
+ else if (c == float.class)
+ sb.append("F");
+ else if (c == double.class)
+ sb.append("D");
+ else if (c == void.class)
+ sb.append("V");
+ else
+ throw new IllegalArgumentException("unknown primitive type: " + c);
+ } else if (c.isArray()) {
+ sb.append("[");
+ sb.append(getDescriptor(c));
+ } else {
+ sb.append("L");
+ sb.append(c.getName().replace('.', '/'));
+ sb.append(";");
+ }
+ return sb.toString();
+ }
+
+}