1 18 19 package alt.jiapi.reflect; 20 21 import java.io.IOException ; 22 import java.io.OutputStream ; 23 import java.io.ByteArrayInputStream ; 24 import java.lang.reflect.Modifier ; 25 import java.net.URL ; 26 import java.util.ArrayList ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.LinkedList ; 31 import java.util.Map ; 32 33 import org.apache.log4j.Category; 34 35 import alt.jiapi.InstrumentationContext; 36 import alt.jiapi.JiapiException; 37 import alt.jiapi.Runtime; 38 39 import alt.jiapi.file.Attribute; 40 import alt.jiapi.file.ClassFile; 41 import alt.jiapi.file.ConstantPool; 42 import alt.jiapi.file.Field; 43 import alt.jiapi.file.Interface; 44 import alt.jiapi.file.Method; 45 46 65 public class JiapiClass { 66 private static final JiapiField[] fieldArrayTemplate = new JiapiField[0]; 68 private static final JiapiMethod[] methodArrayTemplate =new JiapiMethod[0]; 69 70 private static Category log = Runtime.getLogCategory(JiapiClass.class); 71 72 private Loader loader; private ClassBuilder builder; 74 private ClassFile clazz; 75 76 private List jiapiMethods; 77 private List jiapiFields; 78 79 public static void main(String [] args) throws Exception { 81 Loader l = new Loader(); 82 JiapiClass jc = l.loadClass(args[0]); 83 System.out.println(jc); 84 } 85 86 87 96 public static JiapiClass createClass(String name) { 97 ClassFile cf = new ClassFile(name); 98 return new JiapiClass(cf); 99 } 100 101 102 105 public static JiapiClass parseClass(byte[] bytes) throws IOException { 106 ByteArrayInputStream bais = new ByteArrayInputStream (bytes); 107 108 ClassFile cf = ClassFile.parse(bais); 109 return new JiapiClass(cf); 110 } 111 112 113 private JiapiClass() { 114 } 115 116 117 JiapiClass(ClassFile classFile) { 118 this.clazz = classFile; 119 this.builder = new ClassBuilder(classFile); 120 this.loader = new Loader(); 121 122 jiapiMethods = new LinkedList (); 123 jiapiFields = new LinkedList (); 124 125 List methods = clazz.getMethods(); 126 Iterator i = methods.iterator(); 127 while(i.hasNext()) { 128 Method m = (Method)i.next(); 129 130 JiapiMethod jm = new JiapiMethod(m); 131 jm.setDeclaringClass(this); 132 133 jiapiMethods.add(jm); 134 } 135 136 137 List fields = clazz.getFields(); 138 i = fields.iterator(); 139 while(i.hasNext()) { 140 Field f = (Field)i.next(); 141 142 JiapiField jf = new JiapiField(f); 143 jf.setDeclaringClass(this); 144 145 jiapiFields.add(jf); 146 } 147 } 148 149 150 154 public void dump(OutputStream out) throws IOException { 155 out.write(getByteCode()); 156 } 157 158 159 164 public Loader getLoader() { 165 return loader; 166 } 167 168 169 174 public String getName() { 175 return clazz.getClassName(); 176 } 177 178 184 public String getPackageName() { 185 String cName = getName(); 186 int idx = cName.lastIndexOf('.'); if (idx == -1) { 188 return null; 189 } 190 191 return cName.substring(0, idx); 192 } 193 194 199 public byte[] getByteCode() { 200 JiapiMethod[] methods = getDeclaredMethods(); 202 for(int i = 0; i < methods.length; i++) { 203 methods[i].update(); 204 } 205 206 return clazz.toBytes(); 207 } 208 209 210 218 public JiapiMethod[] getMethods() throws ClassNotFoundException { 219 ArrayList al = new ArrayList (); 220 JiapiClass jc = this; 221 222 do { 223 al.addAll(jc.jiapiMethods); 224 } 225 while((jc = jc.getSuperclass()) != null); 226 227 return (JiapiMethod[])al.toArray(methodArrayTemplate); 228 } 229 230 238 public JiapiMethod[] getDeclaredMethods() { 239 ArrayList al = new ArrayList (); 240 al.addAll(jiapiMethods); 241 242 return (JiapiMethod[])al.toArray(methodArrayTemplate); 243 } 244 245 246 264 public JiapiMethod getDeclaredMethod(String name, 265 String [] parameterTypeNames) throws NoSuchMethodException { 266 Signature otherSignature = new Signature("void", parameterTypeNames); 267 268 Iterator i = jiapiMethods.iterator(); 269 while (i.hasNext()) { 270 JiapiMethod jm = (JiapiMethod)i.next(); 271 if (jm.getName().equals(name)) { 272 if (jm.getSignature().equals(otherSignature)) { 273 return jm; 274 } 275 } 276 } 277 278 throw new NoSuchMethodException (name + otherSignature.toString()); 279 } 280 281 289 public JiapiMethod getDeclaredMethod(String name, 290 JiapiClass[] parameterTypes) 291 throws NoSuchMethodException { 292 293 String [] parameterTypeNames = null; 294 if (parameterTypes != null) { 295 parameterTypeNames = new String [parameterTypes.length]; 296 for (int i = 0; i < parameterTypes.length; i++) { 297 parameterTypeNames[i] = parameterTypes[i].getName(); 298 } 299 } 300 301 return getDeclaredMethod(name, parameterTypeNames); 302 } 303 304 305 326 public JiapiMethod getMethod(String name, String [] parameterTypeNames) 327 throws NoSuchMethodException , ClassNotFoundException { 328 JiapiClass jc = this; 329 JiapiMethod method = null; 330 331 do { 332 try { 333 method = jc.getDeclaredMethod(name, parameterTypeNames); 334 return method; 335 } catch (NoSuchMethodException nsme) { 336 } 338 } 339 while ((jc = jc.getSuperclass()) != null); 340 341 throw new NoSuchMethodException (name); 342 } 343 344 354 public JiapiMethod getMethod(String name, JiapiClass[] parameterTypes) 355 throws NoSuchMethodException , ClassNotFoundException { 356 JiapiClass jc = this; 357 JiapiMethod method = null; 358 359 do { 360 try { 361 method = jc.getDeclaredMethod(name, parameterTypes); 362 return method; 363 } catch (NoSuchMethodException nsme) { 364 } 366 } 367 while ((jc = jc.getSuperclass()) != null); 368 369 throw new NoSuchMethodException (name); 370 } 371 372 373 382 public JiapiField[] getFields() throws ClassNotFoundException { 383 ArrayList al = new ArrayList (); 384 JiapiClass jc = this; 385 386 do { 387 al.addAll(jc.jiapiFields); 388 } 389 while ((jc = jc.getSuperclass()) != null); 390 391 return (JiapiField[])al.toArray(fieldArrayTemplate); 392 } 393 394 402 public JiapiField[] getDeclaredFields() { 403 ArrayList al = new ArrayList (); 404 al.addAll(jiapiFields); 405 406 return (JiapiField[])al.toArray(fieldArrayTemplate); 407 } 408 409 416 public JiapiField getDeclaredField(String name) throws NoSuchFieldException { 417 Iterator i = jiapiFields.iterator(); 418 while(i.hasNext()) { 419 JiapiField f = (JiapiField)i.next(); 420 if (f.getName().equals(name)) { 421 return f; 422 } 423 } 424 425 throw new NoSuchFieldException (name); 426 } 427 428 437 public JiapiField getField(String name) throws NoSuchFieldException , ClassNotFoundException { 438 JiapiClass jc = this; 439 JiapiField field = null; 440 441 do { 442 try { 443 field = jc.getDeclaredField(name); 444 return field; 445 } catch (NoSuchFieldException nsfe) { 446 } 448 } 449 while ((jc = jc.getSuperclass()) != null); 450 451 throw new NoSuchFieldException (name); 452 } 453 454 462 public JiapiClass getSuperclass() throws ClassNotFoundException { 463 String scName = clazz.getSuperclassName(); 464 JiapiClass superClass = null; 465 if (scName != null) { 466 try { 467 superClass = loader.loadClass(scName); 468 } 469 catch(IOException ioe) { 470 log.error("", ioe); 471 } 472 } 473 474 return superClass; 475 } 476 477 483 public int getModifiers() { 484 return clazz.getAccessFlags(); 485 } 486 487 488 497 public JiapiField addField(String name) throws FieldExistsException { 498 return addField((short)Modifier.PUBLIC, "java.lang.Object", name); 499 } 500 501 512 public JiapiField addField(int modifiers, String type, String name) throws FieldExistsException { 513 JiapiField jf = builder.addField((short)modifiers, type, name); 514 jf.setDeclaringClass(this); 515 jiapiFields.add(jf); 516 517 return jf; 518 } 519 520 521 522 527 public String [] getInterfaceNames() { 528 ConstantPool cp = clazz.getConstantPool(); 529 List l = clazz.getInterfaces(); 530 531 String [] iNames = new String [l.size()]; 532 for (int i = 0; i < iNames.length; i++) { 533 Interface iFace = (Interface)l.get(i); 534 535 iNames[i] = iFace.getName(); 536 } 537 538 return iNames; 539 } 540 541 546 public JiapiClass[] getInterfaceTypes() throws ClassNotFoundException { 547 String [] iNames = getInterfaceNames(); 548 JiapiClass[] interfaces = new JiapiClass[iNames.length]; 549 550 for (int i = 0; i < interfaces.length; i++) { 551 try { 552 interfaces[i] = getLoader().loadClass(iNames[i]); 553 } 554 catch(java.io.IOException ioe) { 555 throw new ClassNotFoundException (iNames[i]); 556 } 557 } 558 559 return interfaces; 560 } 561 562 569 public void addInterface(String interfaceType) { 570 clazz.addInterface(interfaceType); 571 } 572 573 574 583 public void addInterface(JiapiClass interfaceType) throws IllegalArgumentException { 584 if (!interfaceType.isInterface()) { 585 throw new IllegalArgumentException ("Not an interface: " + 586 interfaceType.getName()); 587 } 588 589 addInterface(interfaceType.getName()); 590 } 591 592 601 public JiapiMethod addMethod(JiapiMethod m) throws MethodExistsException { 602 return addMethod((int)m.getModifiers(), m.getName(), m.getSignature()); 603 } 604 605 618 public JiapiMethod addMethod(int modifiers, String methodName, 619 Signature signature) throws MethodExistsException { 620 JiapiMethod jm = null; 621 Iterator i = jiapiMethods.iterator(); 623 while(i.hasNext()) { 624 JiapiMethod method = (JiapiMethod)i.next(); 625 if (method.getName().equals(methodName) && 626 method.getSignature().getDescriptor().equals(signature.getDescriptor())) { 627 628 throw new MethodExistsException(method); 629 } 630 } 631 632 633 634 try { 635 jm = builder.addMethod((short)modifiers, methodName, signature); 636 } 637 catch(MethodExistsException mee) { 638 jm = mee.getMethod(); 639 jm.setDeclaringClass(this); 640 641 throw mee; 642 } 643 644 jm.setDeclaringClass(this); 645 jiapiMethods.add(jm); 646 647 return jm; 648 } 649 650 651 656 public boolean isInterface() { 657 return Modifier.isInterface(getModifiers()); 658 } 659 660 public String toString() { 661 StringBuffer sb = new StringBuffer (); 662 663 sb.append(Modifier.toString(getModifiers() & 0xffdf)); 666 sb.append(" JiapiClass "); 667 sb.append(getName()); 668 669 String [] interfaces = getInterfaceNames(); 670 if (interfaces.length > 0) { 671 sb.append(" implements "); 672 for (int i = 0; i < interfaces.length; i++) { 673 sb.append(interfaces[i]); 674 if (i < interfaces.length - 1) { 675 sb.append(", "); 676 } 677 } 678 } 679 680 sb.append("\nFields:"); 681 JiapiField[] fields = getDeclaredFields(); 682 for (int i = 0; i < fields.length; i++) { 683 sb.append("\n "); 684 sb.append(fields[i].toString()); 685 } 686 687 sb.append("\nMethods:"); 688 JiapiMethod[] methods = getDeclaredMethods(); 689 for (int i = 0; i < methods.length; i++) { 690 sb.append("\n "); 691 sb.append(methods[i].toString()); 692 693 } 696 697 return sb.toString(); 698 } 699 700 701 void setLoader(Loader l) { 703 this.loader = l; 704 } 705 706 707 712 717 public ConstantPool getConstantPool() { 718 return clazz.getConstantPool(); 719 } 720 } 721 | Popular Tags |