| 1 18 19 package org.objectweb.jac.core.rtti; 20 21 import java.lang.reflect.Constructor ; 22 import java.lang.reflect.Field ; 23 import java.lang.reflect.InvocationTargetException ; 24 import java.lang.reflect.Method ; 25 import java.lang.reflect.Modifier ; 26 import java.util.Arrays ; 27 import java.util.Collection ; 28 import java.util.Enumeration ; 29 import java.util.Hashtable ; 30 import java.util.Iterator ; 31 import java.util.Map ; 32 import java.util.Vector ; 33 import org.apache.log4j.Logger; 34 import org.objectweb.jac.util.Classes; 35 import org.objectweb.jac.util.Strings; 36 37 51 52 public class ClassRepository implements LoadtimeRTTI { 53 static Logger logger = Logger.getLogger("rtti.repository"); 54 static Logger loggerlt = Logger.getLogger("rtti.lt"); 55 56 Map ltClassInfos = new Hashtable (); 57 58 public ClassInfo getClassInfo(String className) { 59 ClassInfo classinfo=(ClassInfo)ltClassInfos.get(className); 60 if (classinfo==null) { 61 classinfo=new ClassInfo(); 62 ltClassInfos.put(className,classinfo); 63 } 64 return classinfo; 65 } 66 67 public void setClassInfo(String className, ClassInfo classInfo) { 68 ltClassInfos.put(className,classInfo); 69 } 70 71 public MethodInfo getMethodInfo(String className, String method) { 72 return getClassInfo(className).getMethodInfo(method); 73 } 74 75 85 86 public void addltModifiedField(String className, String methodSign, 87 String fieldName) { 88 getClassInfo(className).addModifiedField(methodSign,fieldName); 89 } 90 91 public void addltSetField(String className, String methodSign, 92 String fieldName) { 93 getClassInfo(className).addSetField(methodSign,fieldName); 94 } 95 96 106 107 public void addltAccessedField(String className, String methodSign, 108 String fieldName) { 109 getClassInfo(className).addAccessedField(methodSign,fieldName); 110 } 111 112 public void addltReturnedField(String className, String methodSign, 113 String fieldName) { 114 getClassInfo(className).setReturnedField(methodSign,fieldName); 115 } 116 117 public void setltIsGetter(String className, String methodSign, 118 boolean isGetter) { 119 getClassInfo(className).setIsGetter(methodSign,isGetter); 120 } 121 122 public void addltAddedCollection(String className, String methodSign, 123 String fieldName) { 124 getClassInfo(className).addAddedCollection(methodSign,fieldName); 125 } 126 127 public void addltRemovedCollection(String className, String methodSign, 128 String fieldName) { 129 getClassInfo(className).addRemovedCollection(methodSign,fieldName); 130 } 131 132 public void addltModifiedCollection(String className, String methodSign, 133 String fieldName) { 134 getClassInfo(className).addModifiedCollection(methodSign,fieldName); 135 } 136 137 public void setCollectionIndexArgument(String className, String methodSign, 138 int argument) { 139 getClassInfo(className).setCollectionIndexArgument(methodSign,argument); 140 } 141 142 public void setCollectionItemArgument(String className, String methodSign, 143 int argument) { 144 getClassInfo(className).setCollectionItemArgument(methodSign,argument); 145 } 146 147 public void addInvokedMethod(String className, String methodSign, 148 InvokeInfo invokeInfo) { 149 getClassInfo(className).addInvokedMethod(methodSign,invokeInfo); 150 } 151 152 public void setCallSuper(String className, String method) { 153 getMethodInfo(className,method).callSuper = true; 154 } 155 156 160 161 public static ClassRepository get() { 162 if ( classRepository == null ) { 163 classRepository = new ClassRepository(); 164 } 165 return classRepository; 166 } 167 168 170 171 protected static transient ClassRepository classRepository = null; 172 173 174 176 public static Class wrappeeClass; 177 static { 178 try { 179 wrappeeClass = Class.forName("org.objectweb.jac.core.Wrappee"); 181 } catch(Exception e) { 182 e.printStackTrace(); 183 System.exit( -1 ); 184 } 185 } 186 187 190 transient static Hashtable directMethodAccess = new Hashtable (); 191 192 195 transient static Hashtable directFieldAccess = new Hashtable (); 196 197 206 207 public static Hashtable fillDirectMethodAccess(final Class cl) { 208 if( cl == null ) return null; 209 if ( directMethodAccess == null ) directMethodAccess = new Hashtable (); 210 Hashtable methods = new Hashtable (); 211 final Method [] meths = cl.getMethods(); 212 for (int i=meths.length-1; i>=0; i--) { 214 meths[i].setAccessible(true); 215 if ( methods.containsKey(meths[i].getName()) ) { 216 Method [] oldms = (Method []) methods.get( meths[i].getName() ); 217 Method [] newms = new Method [oldms.length+1]; 218 System.arraycopy( oldms, 0, newms, 0, oldms.length ); 219 newms[oldms.length] = meths[i]; 220 methods.remove( meths[i].getName() ); 221 methods.put( meths[i].getName(), newms ); 222 } else { 223 methods.put( meths[i].getName(), new Method [] { meths[i] } ); 224 } 225 } 226 directMethodAccess.put(cl,methods); 227 return methods; 228 } 229 230 237 238 public static void fillDirectFieldAccess(final Class cl) { 239 if (cl==null || cl==Object .class) 240 return; 241 if (directFieldAccess == null ) 242 directFieldAccess = new Hashtable (); 243 if (directFieldAccess.containsKey(cl)) 244 return; 245 Hashtable fields = new Hashtable (); 246 Class superClass = cl.getSuperclass(); 247 if (superClass!=Object .class && superClass!=null) { 248 fillDirectFieldAccess(superClass); 249 Map inheritedFields = (Map )directFieldAccess.get(superClass); 250 if (inheritedFields!=null) 251 fields.putAll(inheritedFields); 252 } 253 final Field [] fs = cl.getDeclaredFields(); 254 for (int i = 0; i<fs.length; i++) { 256 if (!isJacField(fs[i].getName()) && !isSystemField(fs[i].getName())) { 257 fs[i].setAccessible(true); 258 fields.put(fs[i].getName(),fs[i]); 259 } 260 } 261 directFieldAccess.put(cl,fields); 262 } 263 264 275 276 public static Hashtable getDirectFieldAccess(Class cl) { 277 fillDirectFieldAccess(cl); 278 return ((Hashtable )directFieldAccess.get(cl)); 279 } 280 281 291 public static Object invokeDirect(Class cl, 292 String methodName, 293 Object o, 294 Object [] params) 295 throws java.lang.NoSuchMethodException , 296 InvocationTargetException , IllegalAccessException  297 { 298 Method [] directMethods = getDirectMethodAccess(cl,methodName); 299 logger.debug("direct invocation of "+methodName+" => "+ 300 java.util.Arrays.asList(directMethods)); 301 boolean ok = false; 302 boolean lengthOk = false; 303 Object ret = null; 304 for (int i=0; i<directMethods.length; i++) { 305 if (directMethods[i].getParameterTypes().length==params.length) { 306 lengthOk = true; 307 try { 308 ret = directMethods[i].invoke(o, params); 309 ok = true; 310 } catch (IllegalArgumentException e1) { 311 } 312 } 313 } 314 if (!ok) { 315 if (lengthOk) { 316 logger.error("No such method "+cl.getName()+"."+methodName+Arrays.asList(params)); 317 } else { 318 logger.error("Wrong number of parameters for "+cl.getName()+"."+methodName+Arrays.asList(params)); 319 } 320 throw new java.lang.NoSuchMethodException (); 321 } 322 return ret; 323 } 324 325 341 public static Method [] getDirectMethodAccess(Class cl, String name) { 342 Hashtable methods = (Hashtable )directMethodAccess.get(cl); 343 if (methods==null) 344 methods = fillDirectMethodAccess(cl); 345 Method [] ret = (Method []) methods.get(name); 346 if (ret == null ) { 347 return new Method [] { }; 348 } else { 349 return ret; 350 } 351 } 352 353 360 public static boolean isDefaultConstructorAdded(Class cl) { 361 try { 362 cl.getField("__JAC_ADDED_DEFAULT_CONSTRUCTOR"); 363 } catch (Exception e) { 364 return false; 365 } 366 return true; 367 } 368 369 375 public static boolean isJacMethod (String methodName) { 376 if (methodName.startsWith("_")) 377 return true; 378 return false; 379 } 380 381 385 public static boolean isJacField (String fieldName) { 386 return 387 fieldName.startsWith("__JAC_") || 388 fieldName.equals("JUST4LOG_OPTIMIZED"); 389 } 390 391 396 public static boolean isSystemField(String fieldName) { 397 return fieldName.indexOf('$')!=-1; 398 } 399 400 406 public static String [] getMethodsName(Class cl) { 407 408 String [] methodNames = null; 409 Vector tmp = new Vector (); 410 411 try { 412 413 Method [] methods = cl.getMethods(); 414 415 for (int i=0; i<methods.length; i++) { 416 if ( ! ( Modifier.isStatic(methods[i].getModifiers()) || 417 isJacMethod(methods[i].getName()) ) ) { 418 tmp.add (methods[i].getName()); 419 } 420 } 421 422 methodNames = new String [tmp.size()]; 423 424 for (int i=0 ; i<tmp.size(); i++) { 425 methodNames[i] = (String )tmp.get(i); 426 } 427 428 } catch(Exception e) { 429 logger.error("getMethodsName "+cl.getName()+" failed",e); 430 } 431 432 return methodNames; 433 } 434 435 441 public static String [] getModifiersNames(Class cl) { 442 443 ClassItem cli = ClassRepository.get().getClass(cl); 444 Collection modifiers = cli.getAllModifiers(); 445 446 String [] methodNames = new String [modifiers.size()]; 447 448 Iterator it = modifiers.iterator(); 449 for( int i=0; i<methodNames.length; i++ ) { 450 methodNames[i]=((MethodItem)it.next()).getName(); 451 } 452 return methodNames; 453 } 454 455 461 public static String [] getGettersNames(Class cl) { 462 463 ClassItem cli = ClassRepository.get().getClass(cl); 464 Collection getters = cli.getAllGetters(); 465 466 String [] methodNames = new String [getters.size()]; 467 468 Iterator it = getters.iterator(); 469 for( int i=0; i<methodNames.length; i++ ) { 470 methodNames[i]=((MethodItem)it.next()).getName(); 471 } 472 return methodNames; 473 } 474 475 488 public static void addWrittenFields(Class cl, 489 String methodName, 490 String [] fieldNames) 491 { 492 ClassItem cli = ((ClassRepository)ClassRepository.get()).getClass(cl); 493 MethodItem[] mis = cli.getMethods(methodName); 494 495 if ( mis != null ) { 496 for ( int i = 0; i < mis.length; i++ ) { 497 for ( int j = 0; j < fieldNames.length; j++ ) { 498 FieldItem fi = cli.getField( fieldNames[j] ); 499 if ( fi != null ) { 500 mis[i].addWrittenField(fi); 501 } 502 } 503 } 504 } 505 506 } 507 508 521 public static void addAccessedFields(Class cl, 522 String methodName, 523 String [] fieldNames) { 524 525 ClassItem cli = ClassRepository.get().getClass(cl); 526 MethodItem[] mis = cli.getMethods(methodName); 527 528 if ( mis != null ) { 529 for ( int i = 0; i < mis.length; i++ ) { 530 for ( int j = 0; j < fieldNames.length; j++ ) { 531 FieldItem fi = cli.getField( fieldNames[j] ); 532 if ( fi != null ) { 533 mis[i].addAccessedField(fi); 534 } 535 } 536 } 537 } 538 539 } 540 541 554 public static void addAddedCollections(Class cl, 555 String methodName, 556 String [] collectionNames) { 557 558 ClassItem cli = ClassRepository.get().getClass(cl); 559 MethodItem[] mis = cli.getMethods(methodName); 560 561 if ( mis != null ) { 562 for ( int i = 0; i < mis.length; i++ ) { 563 for ( int j = 0; j < collectionNames.length; j++ ) { 564 CollectionItem ci = (CollectionItem)cli.getField(collectionNames[j]); 565 if ( ci != null ) { 566 mis[i].addAddedCollection(ci); 567 } 568 } 569 } 570 } 571 572 } 573 574 587 public static void addRemovedCollections(Class cl, 588 String methodName, 589 String [] collectionNames) { 590 591 ClassItem cli = ClassRepository.get().getClass(cl); 592 MethodItem[] mis = cli.getMethods(methodName); 593 594 if (mis != null) { 595 for (int i=0; i<mis.length; i++) { 596 for (int j=0; j<collectionNames.length; j++) { 597 CollectionItem ci = (CollectionItem)cli.getField(collectionNames[j]); 598 if (ci != null) { 599 mis[i].addRemovedCollection(ci); 600 } 601 } 602 } 603 } 604 605 } 606 607 610 611 public ClassRepository () { 612 classRepository = this; 613 } 614 615 631 public ClassItem getClass(String name) 632 { 633 String wrappedName = Classes.getPrimitiveTypeWrapper(name); 634 MetaItem res = (MetaItem)getObject(wrappedName); 635 if (res == null) { 636 try { 637 res = getClass(Class.forName(name)); 638 } catch (ClassNotFoundException e) { 639 throw new NoSuchClassException(name); 640 } 641 } 642 if (res!=null && res instanceof ClassItem) 643 return (ClassItem)res; 644 else 645 throw new NoSuchClassException(name); 646 } 647 648 659 660 public MetaItem getVirtualClass(String name) 661 { 662 MetaItem ret; 663 try { 664 ret = getClass(name); 665 } catch (NoSuchClassException e) { 666 ret = (MetaItem)getObject(name); 667 if (ret == null) 668 throw e; 669 } 670 return ret; 671 } 672 673 680 public VirtualClassItem getVirtualClassStrict(String name) 681 { 682 MetaItem ret; 683 ret = (MetaItem)getObject(name); 684 if (ret == null || !(ret instanceof VirtualClassItem)) 685 throw new NoSuchClassException(name); 686 return (VirtualClassItem)ret; 687 } 688 689 696 697 public ClassItem getClass(Object object) { 698 return getNonPrimitiveClass(object.getClass().getName()); 699 } 700 708 public ClassItem getClass(Class cl) { 709 String wrappedName = Classes.getPrimitiveTypeWrapper(cl.getName()); 710 MetaItem res = (MetaItem)getObject(wrappedName); 711 if (res == null) { 712 res = buildDefaultRTTI(cl); 713 if (res != null) 714 register(wrappedName, res); 715 } 716 if (res!=null && res instanceof ClassItem) 717 return (ClassItem)res; 718 else 719 throw new NoSuchClassException(cl.getName()); 720 721 } 722 723 public ClassItem getNonPrimitiveClass(String className) { 724 try { 725 Class cl = Class.forName(className); 728 MetaItem res = (MetaItem)getObject(className); 729 if (res == null) { 730 try { 731 res = buildDefaultRTTI(cl); 732 } catch(Exception e) { 733 throw new NoSuchClassException(className); 734 } 735 if (res != null) { 736 register(className, res); 737 return (ClassItem)res; 738 } 739 } else { 740 return (ClassItem)res; 741 } 742 throw new NoSuchClassException(className); 743 } catch(ClassNotFoundException e) { 744 throw new NoSuchClassException(className); 745 } 746 } 747 748 String ignoreFields = null; 749 public void ignoreFields(String packageExpr) { 750 ignoreFields = packageExpr;
|