1 29 30 package com.caucho.bytecode; 31 32 import com.caucho.vfs.ReadStream; 33 import com.caucho.vfs.Vfs; 34 import com.caucho.vfs.WriteStream; 35 36 import java.io.ByteArrayInputStream ; 37 import java.io.IOException ; 38 import java.io.InputStream ; 39 import java.lang.reflect.Modifier ; 40 import java.net.URL ; 41 import java.util.ArrayList ; 42 import java.util.logging.Level ; 43 import java.util.logging.Logger ; 44 45 48 public class JavaClass extends JClass { 49 static private final Logger log 50 = Logger.getLogger(JavaClass.class.getName()); 51 52 public static final int MAGIC = 0xcafebabe; 53 54 public static final int ACC_PUBLIC = 0x0001; 55 public static final int ACC_PRIVATE = 0x0002; 56 public static final int ACC_PROTECTED = 0x0004; 57 public static final int ACC_STATIC = 0x0008; 58 public static final int ACC_FINAL = 0x0010; 59 public static final int ACC_SUPER = 0x0020; 60 61 private JavaClassLoader _loader; 62 63 private URL _url; 64 65 private int _major; 66 private int _minor; 67 68 private ConstantPool _constantPool = new ConstantPool(); 69 70 private int _accessFlags; 71 72 private String _thisClass; 73 private String _superClass; 74 75 private ArrayList <String > _interfaces = new ArrayList <String >(); 76 77 private ArrayList <JavaField> _fields = new ArrayList <JavaField>(); 78 79 private ArrayList <JavaMethod> _methods = new ArrayList <JavaMethod>(); 80 81 private ArrayList <Attribute> _attributes = new ArrayList <Attribute>(); 82 83 private JavaAnnotation []_annotations; 84 85 public JavaClass(JavaClassLoader loader) 86 { 87 if (loader == null) 88 throw new NullPointerException (); 89 90 _loader = loader; 91 } 92 93 96 public JavaClassLoader getClassLoader() 97 { 98 return _loader; 99 } 100 101 104 public void setURL(URL url) 105 { 106 _url = url; 107 } 108 109 112 public void setMajor(int major) 113 { 114 _major = major; 115 } 116 117 120 public int getMajor() 121 { 122 return _major; 123 } 124 125 128 public void setMinor(int minor) 129 { 130 _minor = minor; 131 } 132 133 136 public int getMinor() 137 { 138 return _minor; 139 } 140 141 144 public ConstantPool getConstantPool() 145 { 146 return _constantPool; 147 } 148 149 152 public void setAccessFlags(int flags) 153 { 154 _accessFlags = flags; 155 } 156 157 160 public int getAccessFlags() 161 { 162 lazyLoad(); 163 164 return _accessFlags; 165 } 166 167 170 public void setThisClass(String className) 171 { 172 _thisClass = className; 173 } 174 175 178 public String getThisClass() 179 { 180 return _thisClass; 181 } 182 183 186 public void setSuperClass(String className) 187 { 188 _superClass = className; 189 190 getConstantPool().addClass(className); 191 } 192 193 196 public String getSuperClassName() 197 { 198 lazyLoad(); 199 200 return _superClass; 201 } 202 203 206 public JClass getSuperClass() 207 { 208 lazyLoad(); 209 210 if (_superClass == null) 211 return null; 212 else 213 return getClassLoader().forName(_superClass.replace('/', '.')); 214 } 215 216 219 public boolean isFinal() 220 { 221 return Modifier.isFinal(getAccessFlags()); 222 } 223 224 227 public boolean isAbstract() 228 { 229 return Modifier.isAbstract(getAccessFlags()); 230 } 231 232 235 public boolean isPublic() 236 { 237 return Modifier.isPublic(getAccessFlags()); 238 } 239 240 243 public boolean isPrimitive() 244 { 245 return false; 246 } 247 248 251 public void addInterface(String className) 252 { 253 _interfaces.add(className); 254 } 255 256 259 public ArrayList <String > getInterfaceNames() 260 { 261 return _interfaces; 262 } 263 264 267 public JClass []getInterfaces() 268 { 269 lazyLoad(); 270 271 JClass []interfaces = new JClass[_interfaces.size()]; 272 273 for (int i = 0; i < _interfaces.size(); i++) { 274 String name = _interfaces.get(i); 275 name = name.replace('/', '.'); 276 277 interfaces[i] = getClassLoader().forName(name); 278 } 279 280 return interfaces; 281 } 282 283 286 public void addField(JavaField field) 287 { 288 _fields.add(field); 289 } 290 291 294 public ArrayList <JavaField> getFieldList() 295 { 296 lazyLoad(); 297 298 return _fields; 299 } 300 301 304 public JavaField getField(String name) 305 { 306 ArrayList <JavaField> fieldList = getFieldList(); 307 308 for (int i = 0; i < fieldList.size(); i++) { 309 JavaField field = fieldList.get(i); 310 311 if (field.getName().equals(name)) 312 return field; 313 } 314 315 return null; 316 } 317 318 321 public void addMethod(JavaMethod method) 322 { 323 _methods.add(method); 324 } 325 326 329 public ArrayList <JavaMethod> getMethodList() 330 { 331 lazyLoad(); 332 333 return _methods; 334 } 335 336 339 public boolean isArray() 340 { 341 return false; 342 } 343 344 347 public boolean isInterface() 348 { 349 lazyLoad(); 350 351 return Modifier.isInterface(_accessFlags); 352 } 353 354 357 public JavaMethod getMethod(String name) 358 { 359 ArrayList <JavaMethod> methodList = getMethodList(); 360 361 for (int i = 0; i < methodList.size(); i++) { 362 JavaMethod method = methodList.get(i); 363 364 if (method.getName().equals(name)) 365 return method; 366 } 367 368 return null; 369 } 370 371 374 public JavaMethod findMethod(String name, String descriptor) 375 { 376 ArrayList <JavaMethod> methodList = getMethodList(); 377 378 for (int i = 0; i < methodList.size(); i++) { 379 JavaMethod method = methodList.get(i); 380 381 if (method.getName().equals(name) && 382 method.getDescriptor().equals(descriptor)) 383 return method; 384 } 385 386 return null; 387 } 388 389 392 public void addAttribute(Attribute attr) 393 { 394 _attributes.add(attr); 395 396 attr.addConstants(this); 397 } 398 399 402 public ArrayList <Attribute> getAttributeList() 403 { 404 lazyLoad(); 405 406 return _attributes; 407 } 408 409 412 public Attribute getAttribute(String name) 413 { 414 ArrayList <Attribute> attributeList = getAttributeList(); 415 416 for (int i = attributeList.size() - 1; i >= 0; i--) { 417 Attribute attr = attributeList.get(i); 418 419 if (attr.getName().equals(name)) 420 return attr; 421 } 422 423 return null; 424 } 425 426 430 433 public String getName() 434 { 435 return getThisClass().replace('/', '.'); 436 } 437 438 441 public boolean isAssignableFrom(JClass cl) 442 { 443 if (getName().equals(cl.getName())) 444 return true; 445 446 JClass []ifc = cl.getInterfaces(); 447 448 for (int i = 0; i < ifc.length; i++) { 449 if (isAssignableFrom(ifc[i])) 450 return true; 451 } 452 453 if (cl.getSuperClass() != null) 454 return isAssignableFrom(cl.getSuperClass()); 455 else 456 return false; 457 } 458 459 462 public boolean isAssignableFrom(Class cl) 463 { 464 if (getName().equals(cl.getName())) 465 return true; 466 467 Class []ifc = cl.getInterfaces(); 468 469 for (int i = 0; i < ifc.length; i++) { 470 if (isAssignableFrom(ifc[i])) 471 return true; 472 } 473 474 if (cl.getSuperclass() != null) 475 return isAssignableFrom(cl.getSuperclass()); 476 else 477 return false; 478 } 479 480 483 public boolean isAssignableTo(Class cl) 484 { 485 if (getName().equals(cl.getName())) 486 return true; 487 488 JClass []ifc = getInterfaces(); 489 490 for (int i = 0; i < ifc.length; i++) { 491 if (ifc[i].isAssignableTo(cl)) 492 return true; 493 } 494 495 if (getSuperClass() != null) 496 return getSuperClass().isAssignableTo(cl); 497 else 498 return false; 499 } 500 501 504 public JMethod []getDeclaredMethods() 505 { 506 ArrayList <JavaMethod> methodList = getMethodList(); 507 508 JMethod[] methods = new JMethod[methodList.size()]; 509 510 methodList.toArray(methods); 511 512 return methods; 513 } 514 515 518 public JMethod []getConstructors() 519 { 520 ArrayList <JavaMethod> ctorList = new ArrayList <JavaMethod>(); 521 522 for (JavaMethod method : getMethodList()) { 523 if (method.getName().equals("<init>")) 524 ctorList.add(method); 525 } 526 527 JMethod[] methods = new JMethod[ctorList.size()]; 528 529 ctorList.toArray(methods); 530 531 return methods; 532 } 533 534 537 public JMethod getMethod(String name, JClass []paramTypes) 538 { 539 loop: 540 for (JMethod method : getMethods()) { 541 if (! method.getName().equals(name)) 542 continue; 543 544 JClass []mParamTypes = method.getParameterTypes(); 545 if (mParamTypes.length != paramTypes.length) 546 continue; 547 548 for (int i = 0; i < paramTypes.length; i++) { 549 if (! paramTypes[i].getName().equals(mParamTypes[i].getName())) 550 continue loop; 551 } 552 553 554 return method; 555 } 556 557 return null; 558 } 559 560 563 public JMethod []getMethods() 564 { 565 ArrayList <JMethod> methodList = new ArrayList <JMethod>(); 566 567 getMethods(methodList); 568 569 JMethod []methods = new JMethod[methodList.size()]; 570 methodList.toArray(methods); 571 572 return methods; 573 } 574 575 578 private void getMethods(ArrayList <JMethod> methodList) 579 { 580 for (JMethod method : getDeclaredMethods()) { 581 if (! methodList.contains(method)) 582 methodList.add(method); 583 } 584 585 if (getSuperClass() != null) { 586 for (JMethod method : getSuperClass().getMethods()) { 587 if (! methodList.contains(method)) 588 methodList.add(method); 589 } 590 } 591 } 592 593 596 public JField []getDeclaredFields() 597 { 598 ArrayList <JavaField> fieldList = getFieldList(); 599 600 JField[] fields = new JField[fieldList.size()]; 601 602 fieldList.toArray(fields); 603 604 return fields; 605 } 606 607 610 public JField []getFields() 611 { 612 ArrayList <JField> fieldList = new ArrayList <JField>(); 613 614 getFields(fieldList); 615 616 JField []fields = new JField[fieldList.size()]; 617 fieldList.toArray(fields); 618 619 return fields; 620 } 621 622 625 private void getFields(ArrayList <JField> fieldList) 626 { 627 for (JField field : getDeclaredFields()) { 628 if (! fieldList.contains(field)) 629 fieldList.add(field); 630 } 631 632 if (getSuperClass() != null) { 633 for (JField field : getSuperClass().getFields()) { 634 if (! fieldList.contains(field)) 635 fieldList.add(field); 636 } 637 } 638 } 639 640 643 public JAnnotation []getDeclaredAnnotations() 644 { 645 if (_annotations == null) { 646 Attribute attr = getAttribute("RuntimeVisibleAnnotations"); 647 648 if (attr instanceof OpaqueAttribute) { 649 byte []buffer = ((OpaqueAttribute) attr).getValue(); 650 651 try { 652 ByteArrayInputStream is = new ByteArrayInputStream (buffer); 653 654 ConstantPool cp = getConstantPool(); 655 656 _annotations = JavaAnnotation.parseAnnotations(is, cp, 657 getClassLoader()); 658 } catch (IOException e) { 659 log.log(Level.FINER, e.toString(), e); 660 } 661 } 662 663 if (_annotations == null) { 664 _annotations = new JavaAnnotation[0]; 665 } 666 } 667 668 return _annotations; 669 } 670 671 674 public JAnnotation getAnnotation(String className) 675 { 676 JAnnotation []annList = getDeclaredAnnotations(); 677 678 for (int i = 0; i < annList.length; i++) { 679 if (annList[i].getType().equals(className)) 680 return annList[i]; 681 } 682 683 return null; 684 } 685 686 689 private void lazyLoad() 690 { 691 if (_major > 0) 692 return; 693 694 try { 695 if (_url == null) 696 throw new IllegalStateException (); 697 698 InputStream is = _url.openStream(); 699 ReadStream rs = Vfs.openRead(is); 700 try { 701 _major = 1; 702 703 ByteCodeParser parser = new ByteCodeParser(); 704 parser.setClassLoader(_loader); 705 parser.setJavaClass(this); 706 707 parser.parse(rs); 708 } finally { 709 rs.close(); 710 is.close(); 711 } 712 } catch (RuntimeException e) { 713 throw e; 714 } catch (Exception e) { 715 throw new RuntimeException (e); 716 } 717 } 718 719 722 public void write(WriteStream os) 723 throws IOException 724 { 725 ByteCodeWriter out = new ByteCodeWriter(os, this); 726 727 out.writeInt(MAGIC); 728 out.writeShort(_minor); 729 out.writeShort(_major); 730 731 _constantPool.write(out); 732 733 out.writeShort(_accessFlags); 734 out.writeClass(_thisClass); 735 out.writeClass(_superClass); 736 737 out.writeShort(_interfaces.size()); 738 for (int i = 0; i < _interfaces.size(); i++) { 739 String className = _interfaces.get(i); 740 741 out.writeClass(className); 742 } 743 744 out.writeShort(_fields.size()); 745 for (int i = 0; i < _fields.size(); i++) { 746 JavaField field = _fields.get(i); 747 748 field.write(out); 749 } 750 751 out.writeShort(_methods.size()); 752 for (int i = 0; i < _methods.size(); i++) { 753 JavaMethod method = _methods.get(i); 754 755 method.write(out); 756 } 757 758 out.writeShort(_attributes.size()); 759 for (int i = 0; i < _attributes.size(); i++) { 760 Attribute attr = _attributes.get(i); 761 762 attr.write(out); 763 } 764 } 765 766 public String toString() 767 { 768 return "JavaClass[" + _thisClass + "]"; 769 } 770 } 771 | Popular Tags |