| 1 18 19 package org.objectweb.jac.core.rtti; 20 21 import gnu.regexp.RE; 22 import java.lang.reflect.InvocationTargetException ; 23 import java.lang.reflect.Modifier ; 24 import java.util.Collection ; 25 import java.util.Hashtable ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Vector ; 29 import org.apache.log4j.Logger; 30 import java.lang.reflect.Constructor ; 31 32 39 40 public class ClassItem extends MetaItemDelegate { 41 42 static Logger logger = Logger.getLogger("rtti.class"); 43 44 static Class wrappeeClass = ClassRepository.wrappeeClass; 45 46 52 public ClassItem(Class delegate) throws InvalidDelegateException { 53 super(delegate); 54 Class superClass = delegate.getSuperclass(); 55 if (superClass!=Object .class && superClass!=null) { 56 try { 57 setSuperClass(ClassRepository.get().getClass(superClass)); 58 } catch(Exception e) { 59 logger.error("ClassItem("+delegate.getName()+"): "+e); 60 } 61 } 62 } 63 64 private int collsCount = 0; 65 private int refsCount = 0; 66 private int primsCount = 0; 67 private int methodsCount = 0; 68 private int constructorsCount = 0; 69 70 72 73 protected Hashtable fields = new Hashtable (); 74 75 77 78 protected Hashtable methods = new Hashtable (); 79 80 boolean rttiBuilt = false; 81 82 protected void buildFieldInfo() { 83 if (!rttiBuilt) { 84 rttiBuilt = true; 85 ClassRepository.get().buildDefaultFieldRTTI(this); 86 } 87 } 88 89 99 public FieldItem getField(String name) { 100 buildFieldInfo(); 101 FieldItem ret = getFieldNoError(name); 102 if (ret==null) { 103 throw new NoSuchFieldException (this,name); 104 } 105 return ret; 106 } 107 108 117 public FieldItem getFieldNoError(String name) { 118 buildFieldInfo(); 119 FieldItem field = (FieldItem)fields.get(name); 120 if (field==null) { 121 if (name.indexOf('.')!=-1) { 122 try { 123 List path = parseExpression(name); 124 if (path.get(path.size()-1) instanceof CollectionItem) { 125 field = new CollectionItem(name,path,this); 126 } else { 127 field = new FieldItem(name,path,this); 128 } 129 addField(field); 130 } catch (Exception e) { 131 field = null; 132 logger.error("Expression field "+this.getName()+"."+name+ 133 " instanciation failed: "+e); 134 e.printStackTrace(); 135 } 136 } 137 } 138 if (field==null && superClass!=null) { 139 field = superClass.getFieldNoError(name); 140 if (field!=null) { 141 field = field.clone(this); 142 addField(field); 143 } 144 } 145 return field; 146 } 147 148 152 public List parseExpression(String expression) { 153 Vector path = new Vector (); 154 String current = expression; 155 ClassItem curClass = this; 156 int dot = current.indexOf('.'); 157 FieldItem field = null; 158 while (dot!=-1) { 159 String fieldName = current.substring(0,dot); 160 field = curClass.getField(fieldName); 161 path.add(field); 162 if (field instanceof CollectionItem) 163 curClass = ((CollectionItem)field).getComponentType(); 164 else 165 curClass = field.getTypeItem(); 166 current = current.substring(dot+1); 167 dot = current.indexOf('.'); 168 } 169 170 field = curClass.getField(current); 171 path.add(field); 172 173 179 180 return path; 181 } 182 183 189 190 public CollectionItem getCollection(String name) { 191 buildFieldInfo(); 192 return (CollectionItem) fields.get(name); 193 } 194 195 200 201 public FieldItem[] getFields() { 202 buildFieldInfo(); 203 Collection c = fields.values(); 204 FieldItem[] res = new FieldItem[c.size()]; 205 Iterator it = c.iterator(); 206 int i = 0; 207 while (it.hasNext()) { 208 res[i] = (FieldItem) it.next(); 209 i++; 210 } 211 return res; 212 } 213 214 219 220 public Collection getAllFields() { 221 buildFieldInfo(); 222 return fields.values(); 223 } 224 225 234 public Collection getTaggedFields(String attribute, boolean not) { 235 buildFieldInfo(); 236 Collection c = fields.values(); 237 Iterator it = c.iterator(); 238 Vector result = new Vector (); 239 int i = 0; 240 while (it.hasNext()) { 241 FieldItem field = (FieldItem) it.next(); 242 if (field.getAttribute(attribute)!=null ^ not) { 243 result.add(field); 244 } 245 } 246 return result; 247 } 248 249 252 public Collection filterFields(String expression) { 253 logger.debug(this+".filterFields "+expression); 254 String keyword; 255 boolean not = false; 256 if (expression.charAt(0)=='!') { 257 not = true; 258 expression = expression.substring(1,expression.length()); 259 } 260 int filter = 0; 261 if (expression.equals("static")) 262 filter = Modifier.STATIC; 263 else if (expression.equals("public")) 264 filter = Modifier.PUBLIC; 265 else if (expression.equals("transient")) 266 filter = Modifier.TRANSIENT; 267 else if (expression.equals("private")) 268 filter = Modifier.PRIVATE; 269 else if (expression.equals("protected")) 270 filter = Modifier.PROTECTED; 271 Vector result = new Vector (); 272 Iterator it = fields.values().iterator(); 273 while (it.hasNext()) { 274 FieldItem field = (FieldItem) it.next(); 275 if (((field.getModifiers() & filter) != 0) ^ not) { 276 result.add(field); 277 } 278 } 279 logger.debug(" -> "+result); 280 return result; 281 } 282 283 public Collection getTaggedMethods(String attribute, boolean not) { 284 Collection c = getAllMethods(); 285 Iterator it = c.iterator(); 286 Vector result = new Vector (); 287 int i = 0; 288 while (it.hasNext()) { 289 AbstractMethodItem method = (AbstractMethodItem) it.next(); 290 if (method.getAttribute(attribute)!=null ^ not) { 291 result.add(method); 292 } 293 } 294 return result; 295 } 296 297 public Collection getTaggedMembers(String attribute, boolean not) { 298 Collection result = getTaggedMethods(attribute,not); 299 result.addAll(getTaggedFields(attribute,not)); 300 return result; 301 } 302 303 309 310 public Collection getTaggedMembers(String attribute, Object value) { 311 Collection result = getAllMembers(); 312 Collection result2 = new Vector (); 313 Iterator it = result.iterator(); 314 while (it.hasNext()) { 315 MemberItem member = (MemberItem)it.next(); 316 if (member.getAttribute(attribute)!=null 317 && value.equals(member.getAttribute(attribute))) 318 { 319 result2.add(member); 320 } 321 } 322 return result2; 323 } 324 325 331 public MemberItem getMember(String name) { 332 MemberItem result = null; 333 try { 334 if (name.indexOf('(')!=-1) 335 result = getAbstractMethod(name); 336 else 337 result = getField(name); 338 } catch(NoSuchFieldException e) { 339 if (result==null) { 340 try { 341 result = getAbstractMethod(name); 342 } catch (NoSuchMethodException e2) { 343 throw new NoSuchMemberException(this,name); 344 } 345 } 346 } 347 return result; 348 } 349 350 359 public MemberItem[] getMembers(String [] names) { 360 MemberItem[] tmp = new MemberItem[names.length]; 361 int j = 0; 362 for(int i=0; i<names.length; i++) { 363 try { 364 tmp[j] = getMember(names[i]); 365 j++; 366 } catch (NoSuchMemberException e) { 367 logger.warn(e); 368 } 369 } 370 MemberItem[] members = new MemberItem[j]; 371 System.arraycopy(tmp,0,members,0,j); 372 return members; 373 } 374 375 public Collection getAllMembers() { 376 Collection result = getAllMethods(); 377 result.addAll(getAllFields()); 378 return result; 379 } 380 381 389 public FieldItem[] getFields(String [] names) { 390 FieldItem[] tmp = new FieldItem[names.length]; 391 int j=0; 392 for(int i=0;i<names.length;i++) { 393 try { 394 tmp[j] = getField(names[i]); 395 j++; 396 } catch (NoSuchFieldException e) { 397 logger.warn(e); 398 } 399 } 400 FieldItem[] fields = new FieldItem[j]; 401 System.arraycopy(tmp,0,fields,0,j); 402 return fields; 403 } 404 405 406 415 public MethodItem[] getMethods(String [] names) { 416 MethodItem[] tmp = new MethodItem[names.length]; 417 int j=0; 418 for(int i=0;i<names.length;i++) { 419 try { 420 tmp[j] = getMethod(names[i]); 421 j++; 422 } catch (NoSuchMethodException e) { 423 logger.warn(e); 424 } 425 } 426 MethodItem[] methods = new MethodItem[j]; 427 System.arraycopy(tmp,0,methods,0,j); 428 return methods; 429 } 430 431 436 437 public FieldItem[] getPrimitiveFields() { 438 buildFieldInfo(); 439 Collection c = fields.values(); 440 FieldItem[] res = new FieldItem[primsCount]; 441 Iterator it = c.iterator(); 442 int i = 0; 443 while ( it.hasNext() ) { 444 FieldItem field = (FieldItem) it.next(); 445 if (field.isPrimitive()) { 446 res[i] = field; 447 i++; 448 } 449 } 450 return res; 451 } 452 453 458 459 public FieldItem[] getReferences() { 460 buildFieldInfo(); 461 Collection c = fields.values(); 462 FieldItem[] res = new FieldItem[refsCount]; 463 Iterator it = c.iterator(); 464 int i = 0; 465 while ( it.hasNext() ) { 466 FieldItem field = (FieldItem) it.next(); 467 if (field.isReference()) { 468 res[i] = field; 469 i++; 470 } 471 } 472 return res; 473 } 474 475 480 481 public Collection getMatchingRelations(String expr) { 482 buildFieldInfo(); 483 Vector res = new Vector (); 484 Collection c = fields.values(); 485 Iterator it = c.iterator(); 486 RE re; 487 try { 488 re = new RE(expr); 489 } catch (Exception e) { 490 logger.error("getMatchingRelations "+expr,e); 491 return null; 492 } 493 while (it.hasNext()) { 494 FieldItem field = (FieldItem) it.next(); 495 if (field.isReference() || (field instanceof CollectionItem)) { 496 if (re.isMatch(field.getName())) { 497 res.add( field ); 498 } 499 } 500 } 501 return res; 502 } 503 504 509 510 public CollectionItem[] getCollections() { 511 buildFieldInfo(); 512 Collection c = fields.values(); 513 CollectionItem[] res = new CollectionItem[collsCount]; 514 Iterator it = c.iterator(); 515 int i = 0; 516 while ( it.hasNext() ) { 517 FieldItem field = (FieldItem) it.next(); 518 if (field instanceof CollectionItem) { 519 res[i] = (CollectionItem)field; 520 i++; 521 } 522 } 523 return res; 524 } 525 526 532 void addField(FieldItem field) { 533 buildFieldInfo(); 534 boolean override = fields.containsKey(field.getName()); 535 if (override) { 536 logger.warn("Overriding field "+fields.get(field.getName())+ 537 " with "+field); 538 } 539 try { 540 field.setParent(this); 541 } catch(Exception e) { 542 logger.error("addField "+field.getName(),e); 543 return; 544 } 545 fields.put(field.getName(), field); 546 if (field instanceof CollectionItem && !override) { 547 collsCount++; 548 } else if (field.isReference() && !override) { 549 refsCount++; 550 } else if (!override) { 551 primsCount++; 552 } 553 } 554 555 562 public AbstractMethodItem[] getAbstractMethods(String name) 563 throws NoSuchMethodException  564 { 565 if (name.startsWith("<init>")) 566 name = getShortName()+name.substring(6); 567 AbstractMethodItem[] res=null; 569 if (name.endsWith(")")) { 570 String name2 = name.substring(0,name.indexOf("(")); 571 AbstractMethodItem[] meths = 573 (AbstractMethodItem[])methods.get(name2); 574 if (meths!=null) { 575 for (int i=0; i<meths.length; i++) { 576 if (meths[i].getFullName().endsWith(name)) { 578 res = new AbstractMethodItem[] {meths[i]}; 579 } 580 } 581 } 582 } else { 583 res = (AbstractMethodItem[])methods.get(name); 584 } 585 if (res == null) { 586 throw new NoSuchMethodException ( 587 "ClassItem.getAbstractMethods: no such method "+name+" in "+this); 588 } 589 return res; 590 } 591 592 Hashtable methodCache = new Hashtable (); 593 594 608 public AbstractMethodItem getAbstractMethod(String name) 609 throws NoSuchMethodException , AmbiguousMethodNameException 610 { 611 AbstractMethodItem cachedMethod = 612 (AbstractMethodItem)methodCache.get(name); 613 if (cachedMethod!=null) { 614 return cachedMethod; 615 } else { 616 AbstractMethodItem[] res = getAbstractMethods(name); 617 if (res.length>1) { 618 throw new NoSuchMethodException ("Ambiguous method name "+ 619 this+"."+name); 620 } 621 methodCache.put(name,res[0]); 622 return res[0]; 623 } 624 } 625 626 635 public boolean hasMethod(String name, Class [] paramTypes) { 636 try { 637 ((Class )delegate).getDeclaredMethod(name,paramTypes); 638 return true; 639 } catch(java.lang.NoSuchMethodException e) { 640 return false; 641 } 642 } 643 644 650 static String stripArgs(String name) { 651 int index = name.indexOf("("); 652 if (index!=-1) 653 return name.substring(0,index); 654 else 655 return name; 656 } 657 658 664 665 public MethodItem[] getMethods(String name) 666 throws NoSuchMethodException  667 { 668 MethodItem[] res = null; 669 670 if (name.endsWith(")")) { 672 String name2 = name.substring(0,name.indexOf("(")); 673 MethodItem[] meths = (MethodItem[])methods.get(name2); 675 if (meths!=null) { 676 for (int i=0; i<meths.length; i++) { 677 if (meths[i].getFullName().endsWith(name)) { 679 res = new MethodItem[] {meths[i]}; 680 } 681 } 682 } 683 } else { 684 res = (MethodItem[])methods.get(name); 685 } 686 687 692 693 if (res == null) { 694 throw new NoSuchMethodException ( 696 "ClassItem.getMethods: no such method "+name+" in class "+this); 697 } 698 return res; 699 } 700 701 714 715 public MethodItem getMethod(String name) 716 throws NoSuchMethodException , AmbiguousMethodNameException 717 { 718 MethodItem[] res= getMethods(name); 720 if (res.length>1) { 721 throw new AmbiguousMethodNameException( 722 "Ambiguous method name "+this+"."+name+" choice is:" 723 +java.util.Arrays.asList(res)); 724 } 725 return res[0]; 726 } 727 728 736 public Collection getMethods() { 737 Collection c = methods.values(); 738 Vector res = new Vector (); 739 Iterator it = c.iterator(); 740 while (it.hasNext()) { 741 Object [] methods = (Object []) it.next(); 742 if (methods[0] instanceof MethodItem) { 743 res.add(methods); 744 } 745 } 746 return res; 747 } 748 749 754 public Collection getAllMethods() { 755 Collection c = methods.values(); 756 Vector res = new Vector (); 757 Iterator it = c.iterator(); 758 while (it.hasNext()) { 759 Object [] methods = (Object []) it.next(); 760 for (int i=0; i<methods.length; i++) { 761 if ( methods[i] instanceof MethodItem && 762 !ClassRepository.isJacMethod( 763 ((MethodItem)methods[i]).getName()) ) { 764 res.add(methods[i]); 765 } 766 } 767 } 768 return res; 769 } 770 771 776 public Collection getMixinMethods() { 777 Collection ![]() |