1/* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16package javassist; 17 18import java.io.BufferedOutputStream; 19import java.io.ByteArrayOutputStream; 20import java.io.DataOutputStream; 21import java.io.File; 22import java.io.FileOutputStream; 23import java.io.IOException; 24import java.io.OutputStream; 25import java.net.URL; 26import java.security.ProtectionDomain; 27import java.util.Collection; 28import javassist.bytecode.ClassFile; 29import javassist.bytecode.Descriptor; 30import javassist.bytecode.Opcode; 31import javassist.expr.ExprEditor; 32 33/* Note: 34 * 35 * This class is an abstract class and several methods just return null 36 * or throw an exception. Those methods are overridden in subclasses 37 * of this class. Read the source code of CtClassType if you are 38 * interested in the implementation of Javassist. 39 * 40 * Subclasses of CtClass are CtClassType, CtPrimitiveType, and CtArray. 41 */ 42 43/** 44 * An instance of <code>CtClass</code> represents a class. 45 * It is obtained from <code>ClassPool</code>. 46 * 47 * @see ClassPool#get(String) 48 */ 49public abstract class CtClass { 50 protected String qualifiedName; 51 52 /** 53 * The version number of this release. 54 */ 55 public static final String version = "3.14.0.GA"; 56 57 /** 58 * Prints the version number and the copyright notice. 59 * 60 * <p>The following command invokes this method: 61 * 62 * <ul><pre>java -jar javassist.jar</pre></ul> 63 */ 64 public static void main(String[] args) { 65 System.out.println("Javassist version " + CtClass.version); 66 System.out.println("Copyright (C) 1999-2010 Shigeru Chiba." 67 + " All Rights Reserved."); 68 } 69 70 static final String javaLangObject = "java.lang.Object"; 71 72 /** 73 * The <code>CtClass</code> object representing 74 * the <code>boolean</code> type. 75 */ 76 public static CtClass booleanType; 77 78 /** 79 * The <code>CtClass</code> object representing 80 * the <code>char</code> type. 81 */ 82 public static CtClass charType; 83 84 /** 85 * The <code>CtClass</code> object representing 86 * the <code>byte</code> type. 87 */ 88 public static CtClass byteType; 89 90 /** 91 * The <code>CtClass</code> object representing 92 * the <code>short</code> type. 93 */ 94 public static CtClass shortType; 95 96 /** 97 * The <code>CtClass</code> object representing 98 * the <code>int</code> type. 99 */ 100 public static CtClass intType; 101 102 /** 103 * The <code>CtClass</code> object representing 104 * the <code>long</code> type. 105 */ 106 public static CtClass longType; 107 108 /** 109 * The <code>CtClass</code> object representing 110 * the <code>float</code> type. 111 */ 112 public static CtClass floatType; 113 114 /** 115 * The <code>CtClass</code> object representing 116 * the <code>double</code> type. 117 */ 118 public static CtClass doubleType; 119 120 /** 121 * The <code>CtClass</code> object representing 122 * the <code>void</code> type. 123 */ 124 public static CtClass voidType; 125 126 static CtClass[] primitiveTypes; 127 128 static { 129 primitiveTypes = new CtClass[9]; 130 131 booleanType = 132 new CtPrimitiveType("boolean", 'Z', "java.lang.Boolean", 133 "booleanValue", "()Z", Opcode.IRETURN, 134 Opcode.T_BOOLEAN, 1); 135 primitiveTypes[0] = booleanType; 136 137 charType = new CtPrimitiveType("char", 'C', "java.lang.Character", 138 "charValue", "()C", Opcode.IRETURN, 139 Opcode.T_CHAR, 1); 140 primitiveTypes[1] = charType; 141 142 byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte", 143 "byteValue", "()B", Opcode.IRETURN, 144 Opcode.T_BYTE, 1); 145 primitiveTypes[2] = byteType; 146 147 shortType = new CtPrimitiveType("short", 'S', "java.lang.Short", 148 "shortValue", "()S", Opcode.IRETURN, 149 Opcode.T_SHORT, 1); 150 primitiveTypes[3] = shortType; 151 152 intType = new CtPrimitiveType("int", 'I', "java.lang.Integer", 153 "intValue", "()I", Opcode.IRETURN, 154 Opcode.T_INT, 1); 155 primitiveTypes[4] = intType; 156 157 longType = new CtPrimitiveType("long", 'J', "java.lang.Long", 158 "longValue", "()J", Opcode.LRETURN, 159 Opcode.T_LONG, 2); 160 primitiveTypes[5] = longType; 161 162 floatType = new CtPrimitiveType("float", 'F', "java.lang.Float", 163 "floatValue", "()F", Opcode.FRETURN, 164 Opcode.T_FLOAT, 1); 165 primitiveTypes[6] = floatType; 166 167 doubleType = new CtPrimitiveType("double", 'D', "java.lang.Double", 168 "doubleValue", "()D", Opcode.DRETURN, 169 Opcode.T_DOUBLE, 2); 170 primitiveTypes[7] = doubleType; 171 172 voidType = new CtPrimitiveType("void", 'V', "java.lang.Void", 173 null, null, Opcode.RETURN, 0, 0); 174 primitiveTypes[8] = voidType; 175 } 176 177 protected CtClass(String name) { 178 qualifiedName = name; 179 } 180 181 /** 182 * Converts the object to a string. 183 */ 184 public String toString() { 185 StringBuffer buf = new StringBuffer(getClass().getName()); 186 buf.append("@"); 187 buf.append(Integer.toHexString(hashCode())); 188 buf.append("["); 189 extendToString(buf); 190 buf.append("]"); 191 return buf.toString(); 192 } 193 194 /** 195 * Implemented in subclasses to add to the {@link #toString()} result. 196 * Subclasses should put a space before each token added to the buffer. 197 */ 198 protected void extendToString(StringBuffer buffer) { 199 buffer.append(getName()); 200 } 201 202 /** 203 * Returns a <code>ClassPool</code> for this class. 204 */ 205 public ClassPool getClassPool() { return null; } 206 207 /** 208 * Returns a class file for this class. 209 * 210 * <p>This method is not available if <code>isFrozen()</code> 211 * is true. 212 */ 213 public ClassFile getClassFile() { 214 checkModify(); 215 return getClassFile2(); 216 } 217 218 /** 219 * Returns a class file for this class (read only). 220 * Normal applications do not need calling this method. Use 221 * <code>getClassFile()</code>. 222 * 223 * <p>The <code>ClassFile</code> object obtained by this method 224 * is read only. Changes to this object might not be reflected 225 * on a class file generated by <code>toBytecode()</code>, 226 * <code>toClass()</code>, etc. 227 * 228 * <p>This method is available even if <code>isFrozen()</code> 229 * is true. However, if the class is frozen, it might be also 230 * pruned. 231 * 232 * @see CtClass#getClassFile() 233 * @see CtClass#isFrozen() 234 * @see CtClass#prune() 235 */ 236 public ClassFile getClassFile2() { return null; } 237 238 /** 239 * Undocumented method. Do not use; internal-use only. 240 */ 241 public javassist.compiler.AccessorMaker getAccessorMaker() { 242 return null; 243 } 244 245 /** 246 * Returns the uniform resource locator (URL) of the class file. 247 */ 248 public URL getURL() throws NotFoundException { 249 throw new NotFoundException(getName()); 250 } 251 252 /** 253 * Returns true if the definition of the class has been modified. 254 */ 255 public boolean isModified() { return false; } 256 257 /** 258 * Returns true if the class has been loaded or written out 259 * and thus it cannot be modified any more. 260 * 261 * @see #defrost() 262 * @see #detach() 263 */ 264 public boolean isFrozen() { return true; } 265 266 /** 267 * Makes the class frozen. 268 * 269 * @see #isFrozen() 270 * @see #defrost() 271 * @since 3.6 272 */ 273 public void freeze() {} 274 275 /* Note: this method is overridden by CtClassType 276 */ 277 void checkModify() throws RuntimeException { 278 if (isFrozen()) 279 throw new RuntimeException(getName() + " class is frozen"); 280 281 // isModified() must return true after this method is invoked. 282 } 283 284 /** 285 * Defrosts the class so that the class can be modified again. 286 * 287 * <p>To avoid changes that will be never reflected, 288 * the class is frozen to be unmodifiable if it is loaded or 289 * written out. This method should be called only in a case 290 * that the class will be reloaded or written out later again. 291 * 292 * <p>If <code>defrost()</code> will be called later, pruning 293 * must be disallowed in advance. 294 * 295 * @see #isFrozen() 296 * @see #stopPruning(boolean) 297 * @see #detach() 298 */ 299 public void defrost() { 300 throw new RuntimeException("cannot defrost " + getName()); 301 } 302 303 /** 304 * Returns <code>true</code> if this object represents a primitive 305 * Java type: boolean, byte, char, short, int, long, float, double, 306 * or void. 307 */ 308 public boolean isPrimitive() { return false; } 309 310 /** 311 * Returns <code>true</code> if this object represents an array type. 312 */ 313 public boolean isArray() { 314 return false; 315 } 316 317 /** 318 * If this object represents an array, this method returns the component 319 * type of the array. Otherwise, it returns <code>null</code>. 320 */ 321 public CtClass getComponentType() throws NotFoundException { 322 return null; 323 } 324 325 /** 326 * Returns <code>true</code> if this class extends or implements 327 * <code>clazz</code>. It also returns <code>true</code> if 328 * this class is the same as <code>clazz</code>. 329 */ 330 public boolean subtypeOf(CtClass clazz) throws NotFoundException { 331 return this == clazz || getName().equals(clazz.getName()); 332 } 333 334 /** 335 * Obtains the fully-qualified name of the class. 336 */ 337 public String getName() { return qualifiedName; } 338 339 /** 340 * Obtains the not-qualified class name. 341 */ 342 public final String getSimpleName() { 343 String qname = qualifiedName; 344 int index = qname.lastIndexOf('.'); 345 if (index < 0) 346 return qname; 347 else 348 return qname.substring(index + 1); 349 } 350 351 /** 352 * Obtains the package name. It may be <code>null</code>. 353 */ 354 public final String getPackageName() { 355 String qname = qualifiedName; 356 int index = qname.lastIndexOf('.'); 357 if (index < 0) 358 return null; 359 else 360 return qname.substring(0, index); 361 } 362 363 /** 364 * Sets the class name 365 * 366 * @param name fully-qualified name 367 */ 368 public void setName(String name) { 369 checkModify(); 370 if (name != null) 371 qualifiedName = name; 372 } 373 374 /** 375 * Substitutes <code>newName</code> for all occurrences of a class 376 * name <code>oldName</code> in the class file. 377 * 378 * @param oldName replaced class name 379 * @param newName substituted class name 380 */ 381 public void replaceClassName(String oldName, String newName) { 382 checkModify(); 383 } 384 385 /** 386 * Changes class names appearing in the class file according to the 387 * given <code>map</code>. 388 * 389 * <p>All the class names appearing in the class file are tested 390 * with <code>map</code> to determine whether each class name is 391 * replaced or not. Thus this method can be used for collecting 392 * all the class names in the class file. To do that, first define 393 * a subclass of <code>ClassMap</code> so that <code>get()</code> 394 * records all the given parameters. Then, make an instance of 395 * that subclass as an empty hash-table. Finally, pass that instance 396 * to this method. After this method finishes, that instance would 397 * contain all the class names appearing in the class file. 398 * 399 * @param map the hashtable associating replaced class names 400 * with substituted names. 401 */ 402 public void replaceClassName(ClassMap map) { 403 checkModify(); 404 } 405 406 /** 407 * Returns a collection of the names of all the classes 408 * referenced in this class. 409 * That collection includes the name of this class. 410 * 411 * <p>This method may return <code>null</code>. 412 * 413 * @return a <code>Collection<String></code> object. 414 */ 415 public synchronized Collection getRefClasses() { 416 ClassFile cf = getClassFile2(); 417 if (cf != null) { 418 ClassMap cm = new ClassMap() { 419 public void put(String oldname, String newname) { 420 put0(oldname, newname); 421 } 422 423 public Object get(Object jvmClassName) { 424 String n = toJavaName((String)jvmClassName); 425 put0(n, n); 426 return null; 427 } 428 429 public void fix(String name) {} 430 }; 431 cf.getRefClasses(cm); 432 return cm.values(); 433 } 434 else 435 return null; 436 } 437 438 /** 439 * Determines whether this object represents a class or an interface. 440 * It returns <code>true</code> if this object represents an interface. 441 */ 442 public boolean isInterface() { 443 return false; 444 } 445 446 /** 447 * Determines whether this object represents an annotation type. 448 * It returns <code>true</code> if this object represents an annotation type. 449 * 450 * @since 3.2 451 */ 452 public boolean isAnnotation() { 453 return false; 454 } 455 456 /** 457 * Determines whether this object represents an enum. 458 * It returns <code>true</code> if this object represents an enum. 459 * 460 * @since 3.2 461 */ 462 public boolean isEnum() { 463 return false; 464 } 465 466 /** 467 * Returns the modifiers for this class, encoded in an integer. 468 * For decoding, use <code>javassist.Modifier</code>. 469 * 470 * <p>If the class is a static nested class (a.k.a. static inner class), 471 * the returned modifiers include <code>Modifier.STATIC</code>. 472 * 473 * @see Modifier 474 */ 475 public int getModifiers() { 476 return 0; 477 } 478 479 /** 480 * Returns true if the class has the specified annotation class. 481 * 482 * @param clz the annotation class. 483 * @return <code>true</code> if the annotation is found, otherwise <code>false</code>. 484 * @since 3.11 485 */ 486 public boolean hasAnnotation(Class clz) { 487 return false; 488 } 489 490 /** 491 * Returns the annotation if the class has the specified annotation class. 492 * For example, if an annotation <code>@Author</code> is associated 493 * with this class, an <code>Author</code> object is returned. 494 * The member values can be obtained by calling methods on 495 * the <code>Author</code> object. 496 * 497 * @param clz the annotation class. 498 * @return the annotation if found, otherwise <code>null</code>. 499 * @since 3.11 500 */ 501 public Object getAnnotation(Class clz) throws ClassNotFoundException { 502 return null; 503 } 504 505 /** 506 * Returns the annotations associated with this class. 507 * For example, if an annotation <code>@Author</code> is associated 508 * with this class, the returned array contains an <code>Author</code> 509 * object. The member values can be obtained by calling methods on 510 * the <code>Author</code> object. 511 * 512 * @return an array of annotation-type objects. 513 * @see CtMember#getAnnotations() 514 * @since 3.1 515 */ 516 public Object[] getAnnotations() throws ClassNotFoundException { 517 return new Object[0]; 518 } 519 520 /** 521 * Returns the annotations associated with this class. 522 * This method is equivalent to <code>getAnnotations()</code> 523 * except that, if any annotations are not on the classpath, 524 * they are not included in the returned array. 525 * 526 * @return an array of annotation-type objects. 527 * @see #getAnnotations() 528 * @see CtMember#getAvailableAnnotations() 529 * @since 3.3 530 */ 531 public Object[] getAvailableAnnotations(){ 532 return new Object[0]; 533 } 534 535 /** 536 * Returns an array of nested classes declared in the class. 537 * Nested classes are inner classes, anonymous classes, local classes, 538 * and static nested classes. 539 * 540 * @since 3.2 541 */ 542 public CtClass[] getNestedClasses() throws NotFoundException { 543 return new CtClass[0]; 544 } 545 546 /** 547 * Sets the modifiers. 548 * 549 * <p>If the class is a nested class, this method also modifies 550 * the class declaring that nested class (i.e. the enclosing 551 * class is modified). 552 * 553 * @param mod modifiers encoded by 554 * <code>javassist.Modifier</code> 555 * @see Modifier 556 */ 557 public void setModifiers(int mod) { 558 checkModify(); 559 } 560 561 /** 562 * Determines whether the class directly or indirectly extends 563 * the given class. If this class extends a class A and 564 * the class A extends a class B, then subclassof(B) returns true. 565 * 566 * <p>This method returns true if the given class is identical to 567 * the class represented by this object. 568 */ 569 public boolean subclassOf(CtClass superclass) { 570 return false; 571 } 572 573 /** 574 * Obtains the class object representing the superclass of the 575 * class. 576 * It returns null if this object represents the 577 * <code>java.lang.Object</code> class and thus it does not have 578 * the super class. 579 * 580 * <p>If this object represents an interface, this method 581 * always returns the <code>java.lang.Object</code> class. 582 * To obtain the super interfaces 583 * extended by that interface, call <code>getInterfaces()</code>. 584 */ 585 public CtClass getSuperclass() throws NotFoundException { 586 return null; 587 } 588 589 /** 590 * Changes a super class unless this object represents an interface. 591 * The new super class must be compatible with the old one; for example, 592 * it should inherit from the old super class. 593 * 594 * <p>If this object represents an interface, this method is equivalent 595 * to <code>addInterface()</code>; it appends <code>clazz</code> to 596 * the list of the super interfaces extended by that interface. 597 * Note that an interface can extend multiple super interfaces. 598 * 599 * @see #replaceClassName(String, String) 600 * @see #replaceClassName(ClassMap) 601 */ 602 public void setSuperclass(CtClass clazz) throws CannotCompileException { 603 checkModify(); 604 } 605 606 /** 607 * Obtains the class objects representing the interfaces implemented 608 * by the class or, if this object represents an interface, the interfaces 609 * extended by that interface. 610 */ 611 public CtClass[] getInterfaces() throws NotFoundException { 612 return new CtClass[0]; 613 } 614 615 /** 616 * Sets implemented interfaces. If this object represents an interface, 617 * this method sets the interfaces extended by that interface. 618 * 619 * @param list a list of the <code>CtClass</code> objects 620 * representing interfaces, or 621 * <code>null</code> if the class implements 622 * no interfaces. 623 */ 624 public void setInterfaces(CtClass[] list) { 625 checkModify(); 626 } 627 628 /** 629 * Adds an interface. 630 * 631 * @param anInterface the added interface. 632 */ 633 public void addInterface(CtClass anInterface) { 634 checkModify(); 635 } 636 637 /** 638 * If this class is a member class or interface of another class, 639 * then the class enclosing this class is returned. 640 * 641 * @return null if this class is a top-level class or an anonymous class. 642 */ 643 public CtClass getDeclaringClass() throws NotFoundException { 644 return null; 645 } 646 647 /** 648 * Returns the immediately enclosing method of this class. 649 * This method works only with JDK 1.5 or later. 650 * 651 * @return null if this class is not a local class or an anonymous 652 * class. 653 */ 654 public CtMethod getEnclosingMethod() throws NotFoundException { 655 return null; 656 } 657 658 /** 659 * Makes a new public nested class. If this method is called, 660 * the <code>CtClass</code>, which encloses the nested class, is modified 661 * since a class file includes a list of nested classes. 662 * 663 * <p>The current implementation only supports a static nested class. 664 * <code>isStatic</code> must be true. 665 * 666 * @param name the simple name of the nested class. 667 * @param isStatic true if the nested class is static. 668 */ 669 public CtClass makeNestedClass(String name, boolean isStatic) { 670 throw new RuntimeException(getName() + " is not a class"); 671 } 672 673 /** 674 * Returns an array containing <code>CtField</code> objects 675 * representing all the non-private fields of the class. 676 * That array includes non-private fields inherited from the 677 * superclasses. 678 */ 679 public CtField[] getFields() { return new CtField[0]; } 680 681 /** 682 * Returns the field with the specified name. The returned field 683 * may be a private field declared in a super class or interface. 684 */ 685 public CtField getField(String name) throws NotFoundException { 686 return getField(name, null); 687 } 688 689 /** 690 * Returns the field with the specified name and type. The returned field 691 * may be a private field declared in a super class or interface. 692 * Unlike Java, the JVM allows a class to have 693 * multiple fields with the same name but different types. 694 * 695 * @param name the field name. 696 * @param desc the type descriptor of the field. It is available by 697 * {@link CtField#getSignature()}. 698 * @see CtField#getSignature() 699 */ 700 public CtField getField(String name, String desc) throws NotFoundException { 701 throw new NotFoundException(name); 702 } 703 704 /** 705 * @return null if the specified field is not found. 706 */ 707 CtField getField2(String name, String desc) { return null; } 708 709 /** 710 * Gets all the fields declared in the class. The inherited fields 711 * are not included. 712 * 713 * <p>Note: the result does not include inherited fields. 714 */ 715 public CtField[] getDeclaredFields() { return new CtField[0]; } 716 717 /** 718 * Retrieves the field with the specified name among the fields 719 * declared in the class. 720 * 721 * <p>Note: this method does not search the super classes. 722 */ 723 public CtField getDeclaredField(String name) throws NotFoundException { 724 throw new NotFoundException(name); 725 } 726 727 /** 728 * Retrieves the field with the specified name and type among the fields 729 * declared in the class. Unlike Java, the JVM allows a class to have 730 * multiple fields with the same name but different types. 731 * 732 * <p>Note: this method does not search the super classes. 733 * 734 * @param name the field name. 735 * @param desc the type descriptor of the field. It is available by 736 * {@link CtField#getSignature()}. 737 * @see CtField#getSignature() 738 */ 739 public CtField getDeclaredField(String name, String desc) throws NotFoundException { 740 throw new NotFoundException(name); 741 } 742 743 /** 744 * Gets all the constructors and methods declared in the class. 745 */ 746 public CtBehavior[] getDeclaredBehaviors() { 747 return new CtBehavior[0]; 748 } 749 750 /** 751 * Returns an array containing <code>CtConstructor</code> objects 752 * representing all the non-private constructors of the class. 753 */ 754 public CtConstructor[] getConstructors() { 755 return new CtConstructor[0]; 756 } 757 758 /** 759 * Returns the constructor with the given signature, 760 * which is represented by a character string 761 * called method descriptor. 762 * For details of the method descriptor, see the JVM specification 763 * or <code>javassist.bytecode.Descriptor</code>. 764 * 765 * @param desc method descriptor 766 * @see javassist.bytecode.Descriptor 767 */ 768 public CtConstructor getConstructor(String desc) 769 throws NotFoundException 770 { 771 throw new NotFoundException("no such constructor"); 772 } 773 774 /** 775 * Gets all the constructors declared in the class. 776 * 777 * @see javassist.CtConstructor 778 */ 779 public CtConstructor[] getDeclaredConstructors() { 780 return new CtConstructor[0]; 781 } 782 783 /** 784 * Returns a constructor receiving the specified parameters. 785 * 786 * @param params parameter types. 787 */ 788 public CtConstructor getDeclaredConstructor(CtClass[] params) 789 throws NotFoundException 790 { 791 String desc = Descriptor.ofConstructor(params); 792 return getConstructor(desc); 793 } 794 795 /** 796 * Gets the class initializer (static constructor) 797 * declared in the class. 798 * This method returns <code>null</code> if 799 * no class initializer is not declared. 800 * 801 * @see #makeClassInitializer() 802 * @see javassist.CtConstructor 803 */ 804 public CtConstructor getClassInitializer() { 805 return null; 806 } 807 808 /** 809 * Returns an array containing <code>CtMethod</code> objects 810 * representing all the non-private methods of the class. 811 * That array includes non-private methods inherited from the 812 * superclasses. 813 */ 814 public CtMethod[] getMethods() { 815 return new CtMethod[0]; 816 } 817 818 /** 819 * Returns the method with the given name and signature. 820 * The returned method may be declared in a super class. 821 * The method signature is represented by a character string 822 * called method descriptor, 823 * which is defined in the JVM specification. 824 * 825 * @param name method name 826 * @param desc method descriptor 827 * @see CtBehavior#getSignature() 828 * @see javassist.bytecode.Descriptor 829 */ 830 public CtMethod getMethod(String name, String desc) 831 throws NotFoundException 832 { 833 throw new NotFoundException(name); 834 } 835 836 /** 837 * Gets all methods declared in the class. The inherited methods 838 * are not included. 839 * 840 * @see javassist.CtMethod 841 */ 842 public CtMethod[] getDeclaredMethods() { 843 return new CtMethod[0]; 844 } 845 846 /** 847 * Retrieves the method with the specified name and parameter types 848 * among the methods declared in the class. 849 * 850 * <p>Note: this method does not search the superclasses. 851 * 852 * @param name method name 853 * @param params parameter types 854 * @see javassist.CtMethod 855 */ 856 public CtMethod getDeclaredMethod(String name, CtClass[] params) 857 throws NotFoundException 858 { 859 throw new NotFoundException(name); 860 } 861 862 /** 863 * Retrieves the method with the specified name among the methods 864 * declared in the class. If there are multiple methods with 865 * the specified name, then this method returns one of them. 866 * 867 * <p>Note: this method does not search the superclasses. 868 * 869 * @see javassist.CtMethod 870 */ 871 public CtMethod getDeclaredMethod(String name) throws NotFoundException { 872 throw new NotFoundException(name); 873 } 874 875 /** 876 * Makes an empty class initializer (static constructor). 877 * If the class already includes a class initializer, 878 * this method returns it. 879 * 880 * @see #getClassInitializer() 881 */ 882 public CtConstructor makeClassInitializer() 883 throws CannotCompileException 884 { 885 throw new CannotCompileException("not a class"); 886 } 887 888 /** 889 * Adds a constructor. To add a class initializer (static constructor), 890 * call <code>makeClassInitializer()</code>. 891 * 892 * @see #makeClassInitializer() 893 */ 894 public void addConstructor(CtConstructor c) 895 throws CannotCompileException 896 { 897 checkModify(); 898 } 899 900 /** 901 * Removes a constructor declared in this class. 902 * 903 * @param c removed constructor. 904 * @throws NotFoundException if the constructor is not found. 905 */ 906 public void removeConstructor(CtConstructor c) throws NotFoundException { 907 checkModify(); 908 } 909 910 /** 911 * Adds a method. 912 */ 913 public void addMethod(CtMethod m) throws CannotCompileException { 914 checkModify(); 915 } 916 917 /** 918 * Removes a method declared in this class. 919 * 920 * @param m removed method. 921 * @throws NotFoundException if the method is not found. 922 */ 923 public void removeMethod(CtMethod m) throws NotFoundException { 924 checkModify(); 925 } 926 927 /** 928 * Adds a field. 929 * 930 * <p>The <code>CtField</code> belonging to another 931 * <code>CtClass</code> cannot be directly added to this class. 932 * Only a field created for this class can be added. 933 * 934 * @see javassist.CtField#CtField(CtField,CtClass) 935 */ 936 public void addField(CtField f) throws CannotCompileException { 937 addField(f, (CtField.Initializer)null); 938 } 939 940 /** 941 * Adds a field with an initial value. 942 * 943 * <p>The <code>CtField</code> belonging to another 944 * <code>CtClass</code> cannot be directly added to this class. 945 * Only a field created for this class can be added. 946 * 947 * <p>The initial value is given as an expression written in Java. 948 * Any regular Java expression can be used for specifying the initial 949 * value. The followings are examples. 950 * 951 * <ul><pre> 952 * cc.addField(f, "0") // the initial value is 0. 953 * cc.addField(f, "i + 1") // i + 1. 954 * cc.addField(f, "new Point()"); // a Point object. 955 * </pre></ul> 956 * 957 * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>. 958 * The type of <code>f</code> is <code>CtField</code>. 959 * 960 * <p>Note: do not change the modifier of the field 961 * (in particular, do not add or remove <code>static</code> 962 * to/from the modifier) 963 * after it is added to the class by <code>addField()</code>. 964 * 965 * @param init an expression for the initial value. 966 * 967 * @see javassist.CtField.Initializer#byExpr(String) 968 * @see javassist.CtField#CtField(CtField,CtClass) 969 */ 970 public void addField(CtField f, String init) 971 throws CannotCompileException 972 { 973 checkModify(); 974 } 975 976 /** 977 * Adds a field with an initial value. 978 * 979 * <p>The <code>CtField</code> belonging to another 980 * <code>CtClass</code> cannot be directly added to this class. 981 * Only a field created for this class can be added. 982 * 983 * <p>For example, 984 * 985 * <ul><pre> 986 * CtClass cc = ...; 987 * addField(new CtField(CtClass.intType, "i", cc), 988 * CtField.Initializer.constant(1)); 989 * </pre></ul> 990 * 991 * <p>This code adds an <code>int</code> field named "i". The 992 * initial value of this field is 1. 993 * 994 * @param init specifies the initial value of the field. 995 * 996 * @see javassist.CtField#CtField(CtField,CtClass) 997 */ 998 public void addField(CtField f, CtField.Initializer init) 999 throws CannotCompileException 1000 { 1001 checkModify(); 1002 } 1003 1004 /** 1005 * Removes a field declared in this class. 1006 * 1007 * @param f removed field. 1008 * @throws NotFoundException if the field is not found. 1009 */ 1010 public void removeField(CtField f) throws NotFoundException { 1011 checkModify(); 1012 } 1013 1014 /** 1015 * Obtains an attribute with the given name. 1016 * If that attribute is not found in the class file, this 1017 * method returns null. 1018 * 1019 * <p>This is a convenient method mainly for obtaining 1020 * a user-defined attribute. For dealing with attributes, see the 1021 * <code>javassist.bytecode</code> package. For example, the following 1022 * expression returns all the attributes of a class file. 1023 * 1024 * <ul><pre> 1025 * getClassFile().getAttributes() 1026 * </pre></ul> 1027 * 1028 * @param name attribute name 1029 * @see javassist.bytecode.AttributeInfo 1030 */ 1031 public byte[] getAttribute(String name) { 1032 return null; 1033 } 1034 1035 /** 1036 * Adds a named attribute. 1037 * An arbitrary data (smaller than 64Kb) can be saved in the class 1038 * file. Some attribute name are reserved by the JVM. 1039 * The attributes with the non-reserved names are ignored when a 1040 * class file is loaded into the JVM. 1041 * If there is already an attribute with 1042 * the same name, this method substitutes the new one for it. 1043 * 1044 * <p>This is a convenient method mainly for adding 1045 * a user-defined attribute. For dealing with attributes, see the 1046 * <code>javassist.bytecode</code> package. For example, the following 1047 * expression adds an attribute <code>info</code> to a class file. 1048 * 1049 * <ul><pre> 1050 * getClassFile().addAttribute(info) 1051 * </pre></ul> 1052 * 1053 * @param name attribute name 1054 * @param data attribute value 1055 * @see javassist.bytecode.AttributeInfo 1056 */ 1057 public void setAttribute(String name, byte[] data) { 1058 checkModify(); 1059 } 1060 1061 /** 1062 * Applies the given converter to all methods and constructors 1063 * declared in the class. This method calls <code>instrument()</code> 1064 * on every <code>CtMethod</code> and <code>CtConstructor</code> object 1065 * in the class. 1066 * 1067 * @param converter specifies how to modify. 1068 */ 1069 public void instrument(CodeConverter converter) 1070 throws CannotCompileException 1071 { 1072 checkModify(); 1073 } 1074 1075 /** 1076 * Modifies the bodies of all methods and constructors 1077 * declared in the class. This method calls <code>instrument()</code> 1078 * on every <code>CtMethod</code> and <code>CtConstructor</code> object 1079 * in the class. 1080 * 1081 * @param editor specifies how to modify. 1082 */ 1083 public void instrument(ExprEditor editor) 1084 throws CannotCompileException 1085 { 1086 checkModify(); 1087 } 1088 1089 /** 1090 * Converts this class to a <code>java.lang.Class</code> object. 1091 * Once this method is called, further modifications are not 1092 * allowed any more. 1093 * To load the class, this method uses the context class loader 1094 * of the current thread. If the program is running on some application 1095 * server, the context class loader might be inappropriate to load the 1096 * class. 1097 * 1098 * <p>This method is provided for convenience. If you need more 1099 * complex functionality, you should write your own class loader. 1100 * 1101 * <p>Note: this method calls <code>toClass()</code> 1102 * in <code>ClassPool</code>. 1103 * 1104 * <p><b>Warining:</b> A Class object returned by this method may not 1105 * work with a security manager or a signed jar file because a 1106 * protection domain is not specified. 1107 * 1108 * @see #toClass(java.lang.ClassLoader,ProtectionDomain) 1109 * @see ClassPool#toClass(CtClass) 1110 */ 1111 public Class toClass() throws CannotCompileException { 1112 return getClassPool().toClass(this); 1113 } 1114 1115 /** 1116 * Converts this class to a <code>java.lang.Class</code> object. 1117 * Once this method is called, further modifications are not allowed 1118 * any more. 1119 * 1120 * <p>The class file represented by this <code>CtClass</code> is 1121 * loaded by the given class loader to construct a 1122 * <code>java.lang.Class</code> object. Since a private method 1123 * on the class loader is invoked through the reflection API, 1124 * the caller must have permissions to do that. 1125 * 1126 * <p>An easy way to obtain <code>ProtectionDomain</code> object is 1127 * to call <code>getProtectionDomain()</code> 1128 * in <code>java.lang.Class</code>. It returns the domain that 1129 * the class belongs to. 1130 * 1131 * <p>This method is provided for convenience. If you need more 1132 * complex functionality, you should write your own class loader. 1133 * 1134 * <p>Note: this method calls <code>toClass()</code> 1135 * in <code>ClassPool</code>. 1136 * 1137 * @param loader the class loader used to load this class. 1138 * If it is null, the class loader returned by 1139 * {@link ClassPool#getClassLoader()} is used. 1140 * @param domain the protection domain that the class belongs to. 1141 * If it is null, the default domain created 1142 * by <code>java.lang.ClassLoader</code> is used. 1143 * @see ClassPool#toClass(CtClass,java.lang.ClassLoader) 1144 * @since 3.3 1145 */ 1146 public Class toClass(ClassLoader loader, ProtectionDomain domain) 1147 throws CannotCompileException 1148 { 1149 ClassPool cp = getClassPool(); 1150 if (loader == null) 1151 loader = cp.getClassLoader(); 1152 1153 return cp.toClass(this, loader, domain); 1154 } 1155 1156 /** 1157 * Converts this class to a <code>java.lang.Class</code> object. 1158 * 1159 * <p><b>Warining:</b> A Class object returned by this method may not 1160 * work with a security manager or a signed jar file because a 1161 * protection domain is not specified. 1162 * 1163 * @deprecated Replaced by {@link #toClass(ClassLoader,ProtectionDomain)} 1164 */ 1165 public final Class toClass(ClassLoader loader) 1166 throws CannotCompileException 1167 { 1168 return getClassPool().toClass(this, loader); 1169 } 1170 1171 /** 1172 * Removes this <code>CtClass</code> object from the 1173 * <code>ClassPool</code>. 1174 * After this method is called, any method cannot be called on the 1175 * removed <code>CtClass</code> object. 1176 * 1177 * <p>If <code>get()</code> in <code>ClassPool</code> is called 1178 * with the name of the removed method, 1179 * the <code>ClassPool</code> will read the class file again 1180 * and constructs another <code>CtClass</code> object representing 1181 * the same class. 1182 */ 1183 public void detach() { 1184 ClassPool cp = getClassPool(); 1185 CtClass obj = cp.removeCached(getName()); 1186 if (obj != this) 1187 cp.cacheCtClass(getName(), obj, false); 1188 } 1189 1190 /** 1191 * Disallows (or allows) automatically pruning this <code>CtClass</code> 1192 * object. 1193 * 1194 * <p> 1195 * Javassist can automatically prune a <code>CtClass</code> object 1196 * when <code>toBytecode()</code> (or <code>toClass()</code>, 1197 * <code>writeFile()</code>) is called. 1198 * Since a <code>ClassPool</code> holds all instances of <code>CtClass</code> 1199 * even after <code>toBytecode()</code> (or <code>toClass()</code>, 1200 * <code>writeFile()</code>) is called, pruning may significantly 1201 * save memory consumption. 1202 * 1203 * <p>If <code>ClassPool.doPruning</code> is true, the automatic pruning 1204 * is on by default. Otherwise, it is off. The default value of 1205 * <code>ClassPool.doPruning</code> is false. 1206 * 1207 * @param stop disallow pruning if true. Otherwise, allow. 1208 * @return the previous status of pruning. true if pruning is already stopped. 1209 * 1210 * @see #detach() 1211 * @see #prune() 1212 * @see ClassPool#doPruning 1213 */ 1214 public boolean stopPruning(boolean stop) { return true; } 1215 1216 /** 1217 * Discards unnecessary attributes, in particular, 1218 * <code>CodeAttribute</code>s (method bodies) of the class, 1219 * to minimize the memory footprint. 1220 * After calling this method, the class is read only. 1221 * It cannot be modified any more. 1222 * Furthermore, <code>toBytecode()</code>, 1223 * <code>writeFile()</code>, <code>toClass()</code>, 1224 * or <code>instrument()</code> cannot be called. 1225 * However, the method names and signatures in the class etc. 1226 * are still accessible. 1227 * 1228 * <p><code>toBytecode()</code>, <code>writeFile()</code>, and 1229 * <code>toClass()</code> internally call this method if 1230 * automatic pruning is on. 1231 * 1232 * <p>According to some experiments, pruning does not really reduce 1233 * memory consumption. Only about 20%. Since pruning takes time, 1234 * it might not pay off. So the automatic pruning is off by default. 1235 * 1236 * @see #stopPruning(boolean) 1237 * @see #detach() 1238 * @see ClassPool#doPruning 1239 * 1240 * @see #toBytecode() 1241 * @see #toClass() 1242 * @see #writeFile() 1243 * @see #instrument(CodeConverter) 1244 * @see #instrument(ExprEditor) 1245 */ 1246 public void prune() {} 1247 1248 /* Called by get() in ClassPool. 1249 * CtClassType overrides this method. 1250 */ 1251 void incGetCounter() {} 1252 1253 /** 1254 * If this method is called, the class file will be 1255 * rebuilt when it is finally generated by 1256 * <code>toBytecode()</code> and <code>writeFile()</code>. 1257 * For a performance reason, the symbol table of the 1258 * class file may contain unused entries, for example, 1259 * after a method or a filed is deleted. 1260 * This method 1261 * removes those unused entries. This removal will 1262 * minimize the size of the class file. 1263 * 1264 * @since 3.8.1 1265 */ 1266 public void rebuildClassFile() {} 1267 1268 /** 1269 * Converts this class to a class file. 1270 * Once this method is called, further modifications are not 1271 * possible any more. 1272 * 1273 * @return the contents of the class file. 1274 */ 1275 public byte[] toBytecode() throws IOException, CannotCompileException { 1276 ByteArrayOutputStream barray = new ByteArrayOutputStream(); 1277 DataOutputStream out = new DataOutputStream(barray); 1278 try { 1279 toBytecode(out); 1280 } 1281 finally { 1282 out.close(); 1283 } 1284 1285 return barray.toByteArray(); 1286 } 1287 1288 /** 1289 * Writes a class file represented by this <code>CtClass</code> 1290 * object in the current directory. 1291 * Once this method is called, further modifications are not 1292 * possible any more. 1293 * 1294 * @see #debugWriteFile() 1295 */ 1296 public void writeFile() 1297 throws NotFoundException, IOException, CannotCompileException 1298 { 1299 writeFile("."); 1300 } 1301 1302 /** 1303 * Writes a class file represented by this <code>CtClass</code> 1304 * object on a local disk. 1305 * Once this method is called, further modifications are not 1306 * possible any more. 1307 * 1308 * @param directoryName it must end without a directory separator. 1309 * @see #debugWriteFile(String) 1310 */ 1311 public void writeFile(String directoryName) 1312 throws CannotCompileException, IOException 1313 { 1314 String classname = getName(); 1315 String filename = directoryName + File.separatorChar 1316 + classname.replace('.', File.separatorChar) + ".class"; 1317 int pos = filename.lastIndexOf(File.separatorChar); 1318 if (pos > 0) { 1319 String dir = filename.substring(0, pos); 1320 if (!dir.equals(".")) 1321 new File(dir).mkdirs(); 1322 } 1323 1324 DataOutputStream out 1325 = new DataOutputStream(new BufferedOutputStream( 1326 new DelayedFileOutputStream(filename))); 1327 try { 1328 toBytecode(out); 1329 } 1330 finally { 1331 out.close(); 1332 } 1333 } 1334 1335 /** 1336 * Writes a class file as <code>writeFile()</code> does although this 1337 * method does not prune or freeze the class after writing the class 1338 * file. Note that, once <code>writeFile()</code> or <code>toBytecode()</code> 1339 * is called, it cannot be called again since the class is pruned and frozen. 1340 * This method would be useful for debugging. 1341 */ 1342 public void debugWriteFile() { 1343 debugWriteFile("."); 1344 } 1345 1346 /** 1347 * Writes a class file as <code>writeFile()</code> does although this 1348 * method does not prune or freeze the class after writing the class 1349 * file. Note that, once <code>writeFile()</code> or <code>toBytecode()</code> 1350 * is called, it cannot be called again since the class is pruned and frozen. 1351 * This method would be useful for debugging. 1352 * 1353 * @param directoryName it must end without a directory separator. 1354 */ 1355 public void debugWriteFile(String directoryName) { 1356 try { 1357 boolean p = stopPruning(true); 1358 writeFile(directoryName); 1359 defrost(); 1360 stopPruning(p); 1361 } 1362 catch (Exception e) { 1363 throw new RuntimeException(e); 1364 } 1365 } 1366 1367 static class DelayedFileOutputStream extends OutputStream { 1368 private FileOutputStream file; 1369 private String filename; 1370 1371 DelayedFileOutputStream(String name) { 1372 file = null; 1373 filename = name; 1374 } 1375 1376 private void init() throws IOException { 1377 if (file == null) 1378 file = new FileOutputStream(filename); 1379 } 1380 1381 public void write(int b) throws IOException { 1382 init(); 1383 file.write(b); 1384 } 1385 1386 public void write(byte[] b) throws IOException { 1387 init(); 1388 file.write(b); 1389 } 1390 1391 public void write(byte[] b, int off, int len) throws IOException { 1392 init(); 1393 file.write(b, off, len); 1394 1395 } 1396 1397 public void flush() throws IOException { 1398 init(); 1399 file.flush(); 1400 } 1401 1402 public void close() throws IOException { 1403 init(); 1404 file.close(); 1405 } 1406 } 1407 1408 /** 1409 * Converts this class to a class file. 1410 * Once this method is called, further modifications are not 1411 * possible any more. 1412 * 1413 * <p>This method dose not close the output stream in the end. 1414 * 1415 * @param out the output stream that a class file is written to. 1416 */ 1417 public void toBytecode(DataOutputStream out) 1418 throws CannotCompileException, IOException 1419 { 1420 throw new CannotCompileException("not a class"); 1421 } 1422 1423 /** 1424 * Makes a unique member name. This method guarantees that 1425 * the returned name is not used as a prefix of any methods 1426 * or fields visible in this class. 1427 * If the returned name is XYZ, then any method or field names 1428 * in this class do not start with XYZ. 1429 * 1430 * @param prefix the prefix of the member name. 1431 */ 1432 public String makeUniqueName(String prefix) { 1433 throw new RuntimeException("not available in " + getName()); 1434 } 1435 1436 /* Invoked from ClassPool#compress(). 1437 * This method is overridden by CtClassType. 1438 */ 1439 void compress() {} 1440} 1441