Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame^] | 1 | package aQute.bnd.compatibility; |
| 2 | |
| 3 | import java.lang.reflect.*; |
| 4 | |
| 5 | public class RuntimeSignatureBuilder { |
| 6 | final Scope root; |
| 7 | |
| 8 | public RuntimeSignatureBuilder(Scope root) { |
| 9 | this.root = root; |
| 10 | } |
| 11 | |
| 12 | static public String identity(Class<?> c) { |
| 13 | return Scope.classIdentity(c.getName()); |
| 14 | } |
| 15 | |
| 16 | static public String identity(Method m) { |
| 17 | return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m |
| 18 | .getParameterTypes())); |
| 19 | } |
| 20 | |
| 21 | static public String identity(Constructor<?> m) { |
| 22 | return Scope.constructorIdentity(getDescriptor(void.class, m.getParameterTypes())); |
| 23 | } |
| 24 | |
| 25 | static public String identity(Field m) { |
| 26 | return Scope.fieldIdentity(m.getName(), getDescriptor(m.getType(), null)); |
| 27 | } |
| 28 | |
| 29 | static public String getDescriptor(Class<?> base, Class<?>[] parameters) { |
| 30 | StringBuilder sb = new StringBuilder(); |
| 31 | if (parameters != null) { |
| 32 | sb.append("("); |
| 33 | for (Class<?> parameter : parameters) { |
| 34 | sb.append(getDescriptor(parameter)); |
| 35 | } |
| 36 | sb.append(")"); |
| 37 | } |
| 38 | sb.append(getDescriptor(base)); |
| 39 | return sb.toString(); |
| 40 | } |
| 41 | |
| 42 | public Scope add(Class<?> c) { |
| 43 | Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(), |
| 44 | Kind.CLASS, identity(c), c.getGenericSuperclass(), c.getGenericInterfaces(), null); |
| 45 | |
| 46 | for (Field f : c.getDeclaredFields()) { |
| 47 | add(local, // declaring scope |
| 48 | local, // enclosing |
| 49 | f.getModifiers(), // access modifiers |
| 50 | null, // fields have no type vars |
| 51 | Kind.FIELD, // field |
| 52 | identity(f), // the name of the field |
| 53 | f.getGenericType(), // the type of the field |
| 54 | null, // fields have no parameters |
| 55 | null // fields have no exceptions |
| 56 | ); |
| 57 | } |
| 58 | |
| 59 | for (Constructor<?> constr : c.getConstructors()) { |
| 60 | add(local, // class scope |
| 61 | local, // enclosing |
| 62 | constr.getModifiers(), // access modifiers |
| 63 | constr.getTypeParameters(), // Type vars |
| 64 | Kind.CONSTRUCTOR, // constructor |
| 65 | identity(constr), // <init>(type*) |
| 66 | void.class, // Always void |
| 67 | constr.getGenericParameterTypes(), // parameters types |
| 68 | constr.getGenericExceptionTypes() // exception types |
| 69 | ); |
| 70 | } |
| 71 | |
| 72 | for (Method m : c.getDeclaredMethods()) { |
| 73 | if (m.getDeclaringClass() != Object.class) { |
| 74 | add(local, // class scope |
| 75 | local, // enclosing |
| 76 | m.getModifiers(), // access modifiers |
| 77 | m.getTypeParameters(), Kind.METHOD, // method |
| 78 | identity(m), // <name>(type*)return |
| 79 | m.getGenericReturnType(), // return type |
| 80 | m.getGenericParameterTypes(), // parameter types |
| 81 | m.getGenericExceptionTypes() // exception types |
| 82 | ); |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | return local; |
| 87 | } |
| 88 | |
| 89 | private Scope getEnclosingScope(Class<?> c) { |
| 90 | Method m = c.getEnclosingMethod(); |
| 91 | if (m != null) { |
| 92 | Scope s = getGlobalScope(m.getDeclaringClass()); |
| 93 | return s.getScope(identity(m)); |
| 94 | } |
| 95 | // TODO |
| 96 | // Constructor cnstr = c.getEnclosingConstructor(); |
| 97 | // if (m != null) { |
| 98 | // Scope s = getGlobalScope(cnstr.getDeclaringClass()); |
| 99 | // return s.getScope(identity(cnstr)); |
| 100 | // |
| 101 | // } |
| 102 | Class<?> enclosingClass = c.getEnclosingClass(); |
| 103 | if (enclosingClass != null) { |
| 104 | return getGlobalScope(enclosingClass); |
| 105 | } |
| 106 | |
| 107 | return null; |
| 108 | } |
| 109 | |
| 110 | private Scope getGlobalScope(Class<?> c) { |
| 111 | if (c == null) |
| 112 | return null; |
| 113 | String id = identity(c); |
| 114 | return root.getScope(id); |
| 115 | } |
| 116 | |
| 117 | private Scope add(Scope declaring, Scope enclosing, int modifiers, |
| 118 | TypeVariable<?>[] typeVariables, Kind kind, String id, Type mainType, |
| 119 | Type[] parameterTypes, Type exceptionTypes[]) { |
| 120 | |
| 121 | Scope scope = declaring.getScope(id); |
| 122 | assert scope.access == Access.UNKNOWN; |
| 123 | scope.setAccess(Access.modifier(modifiers)); |
| 124 | scope.setKind(kind); |
| 125 | scope.setGenericParameter(convert(typeVariables)); |
| 126 | scope.setBase(convert(scope,mainType)); |
| 127 | scope.setParameterTypes(convert(parameterTypes)); |
| 128 | scope.setExceptionTypes(convert(exceptionTypes)); |
| 129 | scope.setDeclaring(declaring); |
| 130 | scope.setEnclosing(enclosing); |
| 131 | return scope; |
| 132 | } |
| 133 | |
| 134 | private GenericType convert(Scope source, Type t) { |
| 135 | if (t instanceof ParameterizedType) { |
| 136 | // C<P..> |
| 137 | ParameterizedType pt = (ParameterizedType) t; |
| 138 | /*Scope reference =*/ root.getScope(identity((Class<?>)pt.getRawType())); |
| 139 | Type args[] = pt.getActualTypeArguments(); |
| 140 | GenericType[] arguments = new GenericType[args.length]; |
| 141 | int n = 0; |
| 142 | for (Type arg : args) |
| 143 | arguments[n++] = convert(source,arg); |
| 144 | // return new GenericType(reference,null,arguments); |
| 145 | |
| 146 | } else if (t instanceof TypeVariable) { |
| 147 | // TypeVariable tv = (TypeVariable) t; |
| 148 | // return new GenericType(source,tv.getName(), null); |
| 149 | } else if (t instanceof WildcardType) { |
| 150 | // WildcardType wc = (WildcardType) t; |
| 151 | // wc. |
| 152 | } else if (t instanceof GenericArrayType) { |
| 153 | |
| 154 | } |
| 155 | if (t instanceof Class<?>) { |
| 156 | // raw = ((Class<?>) t).getName() + ";"; |
| 157 | } else |
| 158 | throw new IllegalArgumentException(t.toString()); |
| 159 | |
| 160 | return null; |
| 161 | } |
| 162 | |
| 163 | private GenericParameter[] convert(TypeVariable<?> vars[]) { |
| 164 | if (vars == null) |
| 165 | return null; |
| 166 | |
| 167 | GenericParameter out[] = new GenericParameter[vars.length]; |
| 168 | for (int i = 0; i < vars.length; i++) { |
| 169 | GenericType gss[] = convert(vars[i].getBounds()); |
| 170 | out[i] = new GenericParameter(vars[i].getName(), gss); |
| 171 | } |
| 172 | return out; |
| 173 | } |
| 174 | |
| 175 | private GenericType[] convert(Type[] parameterTypes) { |
| 176 | if (parameterTypes == null || parameterTypes.length == 0) |
| 177 | return GenericType.EMPTY; |
| 178 | |
| 179 | GenericType tss[] = new GenericType[parameterTypes.length]; |
| 180 | for (int i = 0; i < parameterTypes.length; i++) { |
| 181 | //tss[i] = new GenericType(parameterTypes[i]); |
| 182 | } |
| 183 | return tss; |
| 184 | } |
| 185 | |
| 186 | private static String getDescriptor(Class<?> c) { |
| 187 | StringBuilder sb = new StringBuilder(); |
| 188 | if (c.isPrimitive()) { |
| 189 | if (c == boolean.class) |
| 190 | sb.append("Z"); |
| 191 | else if (c == byte.class) |
| 192 | sb.append("Z"); |
| 193 | else if (c == char.class) |
| 194 | sb.append("C"); |
| 195 | else if (c == short.class) |
| 196 | sb.append("S"); |
| 197 | else if (c == int.class) |
| 198 | sb.append("I"); |
| 199 | else if (c == long.class) |
| 200 | sb.append("J"); |
| 201 | else if (c == float.class) |
| 202 | sb.append("F"); |
| 203 | else if (c == double.class) |
| 204 | sb.append("D"); |
| 205 | else if (c == void.class) |
| 206 | sb.append("V"); |
| 207 | else |
| 208 | throw new IllegalArgumentException("unknown primitive type: " + c); |
| 209 | } else if (c.isArray()) { |
| 210 | sb.append("["); |
| 211 | sb.append(getDescriptor(c)); |
| 212 | } else { |
| 213 | sb.append("L"); |
| 214 | sb.append(c.getName().replace('.', '/')); |
| 215 | sb.append(";"); |
| 216 | } |
| 217 | return sb.toString(); |
| 218 | } |
| 219 | |
| 220 | } |