1 16 package org.apache.commons.attributes; 17 18 import java.io.InputStream; 19 import java.io.InputStreamReader; 20 import java.io.BufferedReader; 21 import java.lang.reflect.Constructor; 22 import java.lang.reflect.Method; 23 import java.lang.reflect.Field; 24 import java.net.URL; 25 import java.net.URLConnection; 26 import java.util.ArrayList; 27 import java.util.Collection; 28 import java.util.Collections; 29 import java.util.Enumeration; 30 import java.util.HashMap; 31 import java.util.HashSet; 32 import java.util.Iterator; 33 import java.util.StringTokenizer; 34 35 41 public class AttributeIndex { 42 43 48 public static class MethodParameter { 49 50 private final Method method; 51 private final int index; 52 53 56 public MethodParameter (Method method, int index) { 57 this.method = method; 58 this.index = index; 59 } 60 61 64 public Method getMethod () { 65 return method; 66 } 67 68 71 public int getIndex () { 72 return index; 73 } 74 75 79 public boolean equals (Object o) { 80 return o != null && o instanceof MethodParameter && 81 method.equals (((MethodParameter) o).method) && 82 index == ((MethodParameter) o).index; 83 } 84 85 88 public int hashCode () { 89 return method.hashCode () + index; 90 } 91 92 95 public String toString () { 96 return method.toString () + ":" + index; 97 } 98 } 99 100 105 public static class ConstructorParameter { 106 107 private final Constructor ctor; 108 private final int index; 109 110 111 114 public ConstructorParameter (Constructor ctor, int index) { 115 this.ctor = ctor; 116 this.index = index; 117 } 118 119 122 public Constructor getConstructor () { 123 return ctor; 124 } 125 126 129 public int getIndex () { 130 return index; 131 } 132 133 137 public boolean equals (Object o) { 138 return o != null && o instanceof ConstructorParameter && 139 ctor.equals (((ConstructorParameter) o).ctor) && 140 index == ((ConstructorParameter) o).index; 141 } 142 143 146 public int hashCode () { 147 return ctor.hashCode () + index; 148 } 149 150 153 public String toString () { 154 return ctor.toString () + ":" + index; 155 } 156 } 157 158 private static class IndexNode { 159 public Collection classes = new HashSet (); 160 public Collection fields = new HashSet (); 161 public Collection methods = new HashSet (); 162 public Collection constructors = new HashSet (); 163 public Collection returnValues = new HashSet (); 164 public Collection constructorParameters = new HashSet (); 165 public Collection methodParameters = new HashSet (); 166 167 public void seal () { 168 classes = seal (classes); 169 fields = seal (fields); 170 methods = seal (methods); 171 constructors = seal (constructors); 172 returnValues = seal (returnValues); 173 constructorParameters = seal (constructorParameters); 174 methodParameters = seal (methodParameters); 175 } 176 177 private Collection seal (Collection coll) { 178 return Collections.unmodifiableCollection (coll); 179 } 180 } 181 182 private final HashMap index = new HashMap (); 183 private final ClassLoader classLoader; 184 185 188 public AttributeIndex (ClassLoader cl) throws Exception { 189 this.classLoader = cl; 190 Enumeration enum = cl.getResources ("META-INF/attrs.index"); 191 while (enum.hasMoreElements ()) { 192 URL url = (URL) enum.nextElement (); 193 loadFromURL (url); 194 } 195 196 Iterator iter = index.values ().iterator (); 197 while (iter.hasNext ()) { 198 ((IndexNode) iter.next ()).seal (); 199 } 200 } 201 202 private IndexNode getNode (Class attributeClass) { 203 IndexNode node = (IndexNode) index.get (attributeClass.getName ()); 204 if (node == null) { 205 node = new IndexNode (); 206 index.put (attributeClass.getName (), node); 207 } 208 209 return node; 210 } 211 212 private void addIndex (Collection attributes, Class clazz) { 213 Iterator iter = attributes.iterator (); 214 while (iter.hasNext ()) { 215 getNode (iter.next ().getClass ()).classes.add (clazz); 216 } 217 } 218 219 private void addIndex (Collection attributes, Field field) { 220 Iterator iter = attributes.iterator (); 221 while (iter.hasNext ()) { 222 getNode (iter.next ().getClass ()).fields.add (field); 223 } 224 } 225 226 private void addIndex (Collection attributes, Method method) { 227 Iterator iter = attributes.iterator (); 228 while (iter.hasNext ()) { 229 getNode (iter.next ().getClass ()).methods.add (method); 230 } 231 } 232 233 private void addIndex (Collection attributes, Constructor constructor) { 234 Iterator iter = attributes.iterator (); 235 while (iter.hasNext ()) { 236 getNode (iter.next ().getClass ()).constructors.add (constructor); 237 } 238 } 239 240 private void addReturnIndex (Collection attributes, Method method) { 241 Iterator iter = attributes.iterator (); 242 while (iter.hasNext ()) { 243 getNode (iter.next ().getClass ()).returnValues.add (method); 244 } 245 } 246 247 private void addIndex (Collection attributes, Method method, int parameter) { 248 Iterator iter = attributes.iterator (); 249 while (iter.hasNext ()) { 250 getNode (iter.next ().getClass ()).methodParameters.add (new MethodParameter (method, parameter)); 251 } 252 } 253 254 private void addIndex (Collection attributes, Constructor ctor, int parameter) { 255 Iterator iter = attributes.iterator (); 256 while (iter.hasNext ()) { 257 getNode (iter.next ().getClass ()).constructorParameters.add (new ConstructorParameter (ctor, parameter)); 258 } 259 } 260 261 264 private void addClass (String clazzName) throws Exception { 265 Class clazz = classLoader.loadClass (clazzName); 266 267 Collection coll = Attributes.getAttributes (clazz); 269 270 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class); 271 addIndex (coll, clazz); 272 273 Field[] fields = clazz.getDeclaredFields (); 274 for (int i = 0; i < fields.length; i++) { 275 coll = Attributes.getAttributes (fields[i]); 276 277 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class); 278 addIndex (coll, fields[i]); 279 } 280 281 Method[] methods = clazz.getDeclaredMethods (); 282 for (int i = 0; i < methods.length; i++) { 283 coll = Attributes.getAttributes (methods[i]); 284 285 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class); 286 addIndex (coll, methods[i]); 287 288 coll = Attributes.getReturnAttributes (methods[i]); 290 291 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class); 292 addReturnIndex (coll, methods[i]); 293 294 int numParameters = methods[i].getParameterTypes().length; 296 for (int j = 0; j < numParameters; j++) { 297 coll = Attributes.getParameterAttributes (methods[i], j); 298 299 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class); 300 addIndex (coll, methods[i], j); 301 } 302 } 303 304 Constructor[] ctors = clazz.getDeclaredConstructors (); 305 for (int i = 0; i < ctors.length; i++) { 306 coll = Attributes.getAttributes (ctors[i]); 307 308 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class); 309 addIndex (coll, ctors[i]); 310 311 int numParameters = ctors[i].getParameterTypes().length; 313 for (int j = 0; j < numParameters; j++) { 314 coll = Attributes.getParameterAttributes (ctors[i], j); 315 316 coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class); 317 addIndex (coll, ctors[i], j); 318 } 319 } 320 } 321 322 325 private void loadFromURL (URL url) throws Exception { 326 URLConnection connection = url.openConnection (); 327 BufferedReader br = new BufferedReader (new InputStreamReader (connection.getInputStream ())); 328 try { 329 String currentAttributeClass = null; 330 String line = null; 331 while ((line = br.readLine ()) != null) { 332 if (line.startsWith ("Class: ")) { 333 String className = line.substring ("Class: ".length ()).trim (); 334 addClass (className); 335 } 336 } 337 } finally { 338 br.close (); 339 } 340 } 341 342 348 public Collection getClassesWithAttribute (String attributeClass) { 349 if (index.containsKey (attributeClass)) { 350 Collection classes = ((IndexNode) index.get (attributeClass)).classes; 351 Iterator iter = classes.iterator (); 352 Collection converted = new ArrayList (classes.size ()); 353 while (iter.hasNext ()) { 354 converted.add (((Class) iter.next ()).getName ().replace ('$', '.')); 355 } 356 return converted; 357 } else { 358 return Collections.EMPTY_SET; 359 } 360 } 361 362 368 public Collection getClassesWithAttribute (Class attributeClass) { 369 return getClassesWithAttribute (attributeClass.getName ()); 370 } 371 372 376 public Collection getClasses (Class attributeClass) { 377 if (index.containsKey (attributeClass.getName ())) { 378 return ((IndexNode) index.get (attributeClass.getName ())).classes; 379 } else { 380 return Collections.EMPTY_SET; 381 } 382 } 383 384 388 public Collection getMethods (Class attributeClass) { 389 if (index.containsKey (attributeClass.getName ())) { 390 return ((IndexNode) index.get (attributeClass.getName ())).methods; 391 } else { 392 return Collections.EMPTY_SET; 393 } 394 } 395 396 400 public Collection getMethodsReturning (Class attributeClass) { 401 if (index.containsKey (attributeClass.getName ())) { 402 return ((IndexNode) index.get (attributeClass.getName ())).returnValues; 403 } else { 404 return Collections.EMPTY_SET; 405 } 406 } 407 408 412 public Collection getFields (Class attributeClass) { 413 if (index.containsKey (attributeClass.getName ())) { 414 return ((IndexNode) index.get (attributeClass.getName ())).fields; 415 } else { 416 return Collections.EMPTY_SET; 417 } 418 } 419 420 424 public Collection getConstructors (Class attributeClass) { 425 if (index.containsKey (attributeClass.getName ())) { 426 return ((IndexNode) index.get (attributeClass.getName ())).constructors; 427 } else { 428 return Collections.EMPTY_SET; 429 } 430 } 431 432 436 public Collection getConstructorParameters (Class attributeClass) { 437 if (index.containsKey (attributeClass.getName ())) { 438 return ((IndexNode) index.get (attributeClass.getName ())).constructorParameters; 439 } else { 440 return Collections.EMPTY_SET; 441 } 442 } 443 444 448 public Collection getMethodParameters (Class attributeClass) { 449 if (index.containsKey (attributeClass.getName ())) { 450 return ((IndexNode) index.get (attributeClass.getName ())).methodParameters; 451 } else { 452 return Collections.EMPTY_SET; 453 } 454 } 455 } | Popular Tags |