/Users/lyon/j4p/src/javassist/CtClass.java
|
1 /*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2003 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
16 package javassist;
17
18 import javassist.bytecode.ClassFile;
19 import javassist.bytecode.Descriptor;
20 import javassist.bytecode.Opcode;
21 import javassist.expr.ExprEditor;
22
23 import java.io.DataOutputStream;
24 import java.io.IOException;
25 import java.util.Collection;
26
27 // Subclasses of CtClass: CtClassType, CtPrimitiveType, and CtArray
28
29 /**
30 * An instance of <code>CtClass</code> represents a class.
31 * It is obtained from <code>ClassPool</code>.
32 *
33 * @see ClassPool#get(String)
34 */
35 public abstract class CtClass {
36 protected String qualifiedName;
37
38 /**
39 * The version number of this release.
40 */
41 public static final String version = "2.6";
42
43 static final String javaLangObject = "java.lang.Object";
44
45 /**
46 * The <code>CtClass</code> object representing
47 * the <code>boolean</code> type.
48 */
49 public static CtClass booleanType;
50
51 /**
52 * The <code>CtClass</code> object representing
53 * the <code>char</code> type.
54 */
55 public static CtClass charType;
56
57 /**
58 * The <code>CtClass</code> object representing
59 * the <code>byte</code> type.
60 */
61 public static CtClass byteType;
62
63 /**
64 * The <code>CtClass</code> object representing
65 * the <code>short</code> type.
66 */
67 public static CtClass shortType;
68
69 /**
70 * The <code>CtClass</code> object representing
71 * the <code>int</code> type.
72 */
73 public static CtClass intType;
74
75 /**
76 * The <code>CtClass</code> object representing
77 * the <code>long</code> type.
78 */
79 public static CtClass longType;
80
81 /**
82 * The <code>CtClass</code> object representing
83 * the <code>float</code> type.
84 */
85 public static CtClass floatType;
86
87 /**
88 * The <code>CtClass</code> object representing
89 * the <code>double</code> type.
90 */
91 public static CtClass doubleType;
92
93 /**
94 * The <code>CtClass</code> object representing
95 * the <code>void</code> type.
96 */
97 public static CtClass voidType;
98
99 static CtClass[] primitiveTypes;
100
101 static {
102 primitiveTypes = new CtClass[9];
103
104 booleanType = new CtPrimitiveType("boolean", 'Z', "java.lang.Boolean",
105 "booleanValue", "()Z", Opcode.IRETURN,
106 Opcode.T_BOOLEAN, 1);
107 primitiveTypes[0] = booleanType;
108
109 charType = new CtPrimitiveType("char", 'C', "java.lang.Character",
110 "charValue", "()C", Opcode.IRETURN,
111 Opcode.T_CHAR, 1);
112 primitiveTypes[1] = charType;
113
114 byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte",
115 "byteValue", "()B", Opcode.IRETURN,
116 Opcode.T_BYTE, 1);
117 primitiveTypes[2] = byteType;
118
119 shortType = new CtPrimitiveType("short", 'S', "java.lang.Short",
120 "shortValue", "()S", Opcode.IRETURN,
121 Opcode.T_SHORT, 1);
122 primitiveTypes[3] = shortType;
123
124 intType = new CtPrimitiveType("int", 'I', "java.lang.Integer",
125 "intValue", "()I", Opcode.IRETURN,
126 Opcode.T_INT, 1);
127 primitiveTypes[4] = intType;
128
129 longType = new CtPrimitiveType("long", 'J', "java.lang.Long",
130 "longValue", "()J", Opcode.LRETURN,
131 Opcode.T_LONG, 2);
132 primitiveTypes[5] = longType;
133
134 floatType = new CtPrimitiveType("float", 'F', "java.lang.Float",
135 "floatValue", "()F", Opcode.FRETURN,
136 Opcode.T_FLOAT, 1);
137 primitiveTypes[6] = floatType;
138
139 doubleType = new CtPrimitiveType("double", 'D', "java.lang.Double",
140 "doubleValue", "()D", Opcode.DRETURN,
141 Opcode.T_DOUBLE, 2);
142 primitiveTypes[7] = doubleType;
143
144 voidType = new CtPrimitiveType("void", 'V', "java.lang.Void",
145 null, null, Opcode.RETURN, 0, 0);
146 primitiveTypes[8] = voidType;
147 }
148
149 protected CtClass(String name) {
150 qualifiedName = name;
151 }
152
153 /**
154 * Returns a <code>ClassPool</code> for this class.
155 */
156 public ClassPool getClassPool() {
157 return null;
158 }
159
160 /**
161 * Returns a class file for this class.
162 *
163 * <p>This method is not available if <code>isFrozen()</code>
164 * is true.
165 */
166 public ClassFile getClassFile() {
167 checkModify();
168 return getClassFile2();
169 }
170
171 /**
172 * Undocumented method. Do not use; internal-use only.
173 */
174 public ClassFile getClassFile2() {
175 return null;
176 }
177
178 /**
179 * Returns true if the definition of the class has been modified.
180 */
181 public boolean isModified() {
182 return false;
183 }
184
185 /**
186 * Returns true if the class has been loaded or written out
187 * and thus it cannot be modified any more.
188 *
189 * @see #defrost()
190 */
191 public boolean isFrozen() {
192 return true;
193 }
194
195 void freeze() {
196 }
197
198 void checkModify() throws RuntimeException {
199 if (isFrozen())
200 throw new RuntimeException("the class is frozen");
201
202 // isModified() must return true after this method is invoked.
203 }
204
205 /**
206 * Defrosts the class so that the class can be modified again.
207 *
208 * To avoid changes that will be never reflected,
209 * the class is frozen to be unmodifiable if it is loaded or
210 * written out. This method should be called only in a case
211 * that the class will be reloaded or written out later again.
212 *
213 * @see #isFrozen()
214 */
215 public void defrost() {
216 throw new RuntimeException("cannot defrost " + getName());
217 }
218
219 /**
220 * Returns <code>true</code> if this object represents a primitive
221 * Java type: boolean, byte, char, short, int, long, float, double,
222 * or void.
223 */
224 public boolean isPrimitive() {
225 return false;
226 }
227
228 /**
229 * Returns <code>true</code> if this object represents an array type.
230 */
231 public boolean isArray() {
232 return false;
233 }
234
235 /**
236 * If this object represents an array, this method returns the component
237 * type of the array. Otherwise, it returns <code>null</code>.
238 */
239 public CtClass getComponentType() throws NotFoundException {
240 return null;
241 }
242
243 /**
244 * Returns <code>true</code> if this class extends or implements
245 * <code>clazz</code>. It also returns <code>true</code> if
246 * this class is the same as <code>clazz</code>.
247 */
248 public boolean subtypeOf(CtClass clazz) throws NotFoundException {
249 return this == clazz || getName().equals(clazz.getName());
250 }
251
252 /**
253 * Obtains the fully-qualified name of the class.
254 */
255 public String getName() {
256 return qualifiedName;
257 }
258
259 /**
260 * Obtains the not-qualified class name.
261 */
262 public final String getSimpleName() {
263 String qname = qualifiedName;
264 int index = qname.lastIndexOf('.');
265 if (index < 0)
266 return qname;
267 else
268 return qname.substring(index + 1);
269 }
270
271 /**
272 * Obtains the package name. It may be <code>null</code>.
273 */
274 public final String getPackageName() {
275 String qname = qualifiedName;
276 int index = qname.lastIndexOf('.');
277 if (index < 0)
278 return null;
279 else
280 return qname.substring(0, index);
281 }
282
283 /**
284 * Sets the class name
285 *
286 * @param name fully-qualified name
287 */
288 public void setName(String name) {
289 checkModify();
290 if (name != null)
291 qualifiedName = name;
292 }
293
294 /**
295 * Substitutes <code>newName</code> for all occurrences of a class
296 * name <code>oldName</code> in the class file.
297 *
298 * @param oldname replaced class name
299 * @param newname substituted class name
300 */
301 public void replaceClassName(String oldname, String newname) {
302 checkModify();
303 }
304
305 /**
306 * Changes class names appearing in the class file according to the
307 * given <code>map</code>.
308 *
309 * <p>All the class names appearing in the class file are tested
310 * with <code>map</code> to determine whether each class name is
311 * replaced or not. Thus this method can be used for collecting
312 * all the class names in the class file. To do that, first define
313 * a subclass of <code>ClassMap</code> so that <code>get()</code>
314 * records all the given parameters. Then, make an instance of
315 * that subclass as an empty hash-table. Finally, pass that instance
316 * to this method. After this method finishes, that instance would
317 * contain all the class names appearing in the class file.
318 *
319 * @param map the hashtable associating replaced class names
320 * with substituted names.
321 */
322 public void replaceClassName(ClassMap map) {
323 checkModify();
324 }
325
326 /**
327 * Returns a collection of the names of all the classes
328 * referenced in this class.
329 * That collection includes the name of this class.
330 *
331 * <p>This method may return <code>null</code>.
332 */
333 public Collection getRefClasses() {
334 ClassFile cf = getClassFile2();
335 if (cf != null) {
336 ClassMap cm = new ClassMap() {
337 public void put(String oldname, String newname) {
338 put0(oldname, newname);
339 }
340
341 public Object get(Object jvmClassName) {
342 String n = toJavaName((String) jvmClassName);
343 put0(n, n);
344 return null;
345 }
346
347 public void fix(String name) {
348 }
349 };
350 cf.renameClass(cm);
351 return cm.values();
352 } else
353 return null;
354 }
355
356 /**
357 * Determines whether this object represents a class or an interface.
358 * It returns <code>true</code> if this object represents an interface.
359 */
360 public boolean isInterface() {
361 return false;
362 }
363
364 /**
365 * Returns the modifiers for this class, encoded in an integer.
366 * For decoding, use <code>javassist.Modifier</code>.
367 *
368 * @see Modifier
369 */
370 public int getModifiers() {
371 return 0;
372 }
373
374 /**
375 * Sets the modifiers.
376 *
377 * @param mod modifiers encoded by
378 * <code>javassist.Modifier</code>
379 * @see Modifier
380 */
381 public void setModifiers(int mod) {
382 checkModify();
383 }
384
385 /**
386 * Determines whether the class directly or indirectly extends
387 * the given class. If this class extends a class A and
388 * the class A extends a class B, then subclassof(B) returns true.
389 *
390 * <p>This method returns true if the given class is identical to
391 * the class represented by this object.
392 */
393 public boolean subclassOf(CtClass superclass) {
394 return false;
395 }
396
397 /**
398 * Obtains the class object representing the superclass of the
399 * class.
400 * It returns null if this object represents the
401 * <code>java.lang.Object</code> class and thus it does not have
402 * the super class.
403 */
404 public CtClass getSuperclass() throws NotFoundException {
405 return null;
406 }
407
408 /**
409 * Changes a super class. The new super class must be compatible
410 * with the old one.
411 */
412 public void setSuperclass(CtClass clazz) throws CannotCompileException {
413 checkModify();
414 }
415
416 /**
417 * Obtains the class objects representing the interfaces of the
418 * class.
419 */
420 public CtClass[] getInterfaces() throws NotFoundException {
421 return new CtClass[0];
422 }
423
424 /**
425 * Sets interfaces.
426 *
427 * @param list a list of the <code>CtClass</code> objects
428 * representing interfaces, or
429 * <code>null</code> if the class implements
430 * no interfaces.
431 */
432 public void setInterfaces(CtClass[] list) {
433 checkModify();
434 }
435
436 /**
437 * Adds an interface.
438 *
439 * @param anInterface the added interface.
440 */
441 public void addInterface(CtClass anInterface) {
442 checkModify();
443 }
444
445 /**
446 * Returns an array containing <code>CtField</code> objects
447 * representing all the public fields of the class.
448 * That array includes public fields inherited from the
449 * superclasses.
450 */
451 public CtField[] getFields() {
452 return new CtField[0];
453 }
454
455 /**
456 * Returns the field with the specified name. The returned field
457 * may be a private field declared in a super class or interface.
458 */
459 public CtField getField(String name) throws NotFoundException {
460 throw new NotFoundException(name);
461 }
462
463 /**
464 * Gets all the fields declared in the class. The inherited fields
465 * are not included.
466 *
467 * <p>Note: the result does not include inherited fields.
468 */
469 public CtField[] getDeclaredFields() {
470 return new CtField[0];
471 }
472
473 /**
474 * Retrieves the field with the specified name among the fields
475 * declared in the class.
476 *
477 * <p>Note: this method does not search the superclasses.
478 */
479 public CtField getDeclaredField(String name) throws NotFoundException {
480 throw new NotFoundException(name);
481 }
482
483 /**
484 * Gets all the constructors and methods declared in the class.
485 */
486 public CtBehavior[] getDeclaredBehaviors() {
487 return new CtBehavior[0];
488 }
489
490 /**
491 * Returns an array containing <code>CtConstructor</code> objects
492 * representing all the public constructors of the class.
493 */
494 public CtConstructor[] getConstructors() {
495 return new CtConstructor[0];
496 }
497
498 /**
499 * Returns the constructor with the given signature,
500 * which is represented by a character string
501 * called method descriptor.
502 * For details of the method descriptor, see the JVM specification
503 * or <code>javassist.bytecode.Descriptor</code>.
504 *
505 * @param desc method descriptor
506 * @see javassist.bytecode.Descriptor
507 */
508 public CtConstructor getConstructor(String desc)
509 throws NotFoundException {
510 throw new NotFoundException("no such a constructor");
511 }
512
513 /**
514 * Gets all the constructors declared in the class.
515 *
516 * @see javassist.CtConstructor
517 */
518 public CtConstructor[] getDeclaredConstructors() {
519 return new CtConstructor[0];
520 }
521
522 /**
523 * Returns a constructor receiving the specified parameters.
524 *
525 * @param params parameter types.
526 */
527 public CtConstructor getDeclaredConstructor(CtClass[] params)
528 throws NotFoundException {
529 String desc = Descriptor.ofConstructor(params);
530 return getConstructor(desc);
531 }
532
533 /**
534 * Gets the class initializer (static constructor)
535 * declared in the class.
536 * This method returns <code>null</code> if
537 * no class initializer is not declared.
538 *
539 * @see #makeClassInitializer()
540 * @see javassist.CtConstructor
541 */
542 public CtConstructor getClassInitializer() {
543 return null;
544 }
545
546 /**
547 * Returns an array containing <code>CtMethod</code> objects
548 * representing all the public methods of the class.
549 * That array includes public methods inherited from the
550 * superclasses.
551 */
552 public CtMethod[] getMethods() {
553 return new CtMethod[0];
554 }
555
556 /**
557 * Returns the method with the given name and signature.
558 * The returned method may be declared in a super class.
559 * The method signature is represented by a character string
560 * called method descriptor,
561 * which is defined in the JVM specification.
562 *
563 * @param name method name
564 * @param desc method descriptor
565 * @see javassist.bytecode.Descriptor
566 */
567 public CtMethod getMethod(String name, String desc)
568 throws NotFoundException {
569 throw new NotFoundException(name);
570 }
571
572 /**
573 * Gets all methods declared in the class. The inherited methods
574 * are not included.
575 *
576 * @see javassist.CtMethod
577 */
578 public CtMethod[] getDeclaredMethods() {
579 return new CtMethod[0];
580 }
581
582 /**
583 * Retrieves the method with the specified name and parameter types
584 * among the methods declared in the class.
585 *
586 * <p>Note: this method does not search the superclasses.
587 *
588 * @param name method name
589 * @param params parameter types
590 * @see javassist.CtMethod
591 */
592 public CtMethod getDeclaredMethod(String name, CtClass[] params)
593 throws NotFoundException {
594 throw new NotFoundException(name);
595 }
596
597 /**
598 * Retrieves the method with the specified name among the methods
599 * declared in the class. If there are multiple methods with
600 * the specified name, then this method returns one of them.
601 *
602 * <p>Note: this method does not search the superclasses.
603 *
604 * @see javassist.CtMethod
605 */
606 public CtMethod getDeclaredMethod(String name) throws NotFoundException {
607 throw new NotFoundException(name);
608 }
609
610 /**
611 * Makes a class initializer (static constructor).
612 * If the class already includes a class initializer,
613 * this method returns it.
614 *
615 * @see #getClassInitializer()
616 */
617 public CtConstructor makeClassInitializer()
618 throws CannotCompileException {
619 throw new CannotCompileException("not a class");
620 }
621
622 /**
623 * Adds a constructor.
624 */
625 public void addConstructor(CtConstructor c)
626 throws CannotCompileException {
627 checkModify();
628 }
629
630 /**
631 * Adds a method.
632 */
633 public void addMethod(CtMethod m) throws CannotCompileException {
634 checkModify();
635 }
636
637 /**
638 * Adds a field.
639 *
640 * <p>The <code>CtField</code> belonging to another
641 * <code>CtClass</code> cannot be directly added to this class.
642 * Only a field created for this class can be added.
643 *
644 * @see javassist.CtField#CtField(CtField,CtClass)
645 */
646 public void addField(CtField f) throws CannotCompileException {
647 addField(f, (CtField.Initializer) null);
648 }
649
650 /**
651 * Adds a field with an initial value.
652 *
653 * <p>The <code>CtField</code> belonging to another
654 * <code>CtClass</code> cannot be directly added to this class.
655 * Only a field created for this class can be added.
656 *
657 * <p>The initial value is given as an expression written in Java.
658 * Any regular Java expression can be used for specifying the initial
659 * value. The followings are examples.
660 *
661 * <ul><pre>
662 * cc.addField(f, "0") // the initial value is 0.
663 * cc.addField(f, "i + 1") // i + 1.
664 * cc.addField(f, "new Point()"); // a Point object.
665 * </pre></ul>
666 *
667 * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>.
668 * The type of <code>f</code> is <code>CtField</code>.
669 *
670 * @param init an expression for the initial value.
671 *
672 * @see javassist.CtField.Initializer#byExpr(String)
673 * @see javassist.CtField#CtField(CtField,CtClass)
674 */
675 public void addField(CtField f, String init)
676 throws CannotCompileException {
677 checkModify();
678 }
679
680 /**
681 * Adds a field with an initial value.
682 *
683 * <p>The <code>CtField</code> belonging to another
684 * <code>CtClass</code> cannot be directly added to this class.
685 * Only a field created for this class can be added.
686 *
687 * <p>For example,
688 *
689 * <ul><pre>
690 * CtClass cc = ...;
691 * addField(new CtField(CtClass.intType, "i", cc),
692 * CtField.Initializer.constant(1));
693 * </pre></ul>
694 *
695 * <p>This code adds an <code>int</code> field named "i". The
696 * initial value of this field is 1.
697 *
698 * @param init specifies the initial value of the field.
699 *
700 * @see javassist.CtField#CtField(CtField,CtClass)
701 */
702 public void addField(CtField f, CtField.Initializer init)
703 throws CannotCompileException {
704 checkModify();
705 }
706
707 /**
708 * Obtains an attribute with the given name.
709 * If that attribute is not found in the class file, this
710 * method returns null.
711 *
712 * @param name attribute name
713 */
714 public byte[] getAttribute(String name) {
715 return null;
716 }
717
718 /**
719 * Adds a named attribute.
720 * An arbitrary data (smaller than 64Kb) can be saved in the class
721 * file. Some attribute name are reserved by the JVM.
722 * The attributes with the non-reserved names are ignored when a
723 * class file is loaded into the JVM.
724 * If there is already an attribute with
725 * the same name, this method substitutes the new one for it.
726 *
727 * @param name attribute name
728 * @param data attribute value
729 */
730 public void setAttribute(String name, byte[] data) {
731 checkModify();
732 }
733
734 /**
735 * Applies the given converter to all methods and constructors
736 * declared in the class. This method calls <code>instrument()</code>
737 * on every <code>CtMethod</code> and <code>CtConstructor</code> object
738 * in the class.
739 *
740 * @param converter specifies how to modify.
741 */
742 public void instrument(CodeConverter converter)
743 throws CannotCompileException {
744 checkModify();
745 }
746
747 /**
748 * Modifies the bodies of all methods and constructors
749 * declared in the class. This method calls <code>instrument()</code>
750 * on every <code>CtMethod</code> and <code>CtConstructor</code> object
751 * in the class.
752 *
753 * @param editor specifies how to modify.
754 */
755 public void instrument(ExprEditor editor)
756 throws CannotCompileException {
757 checkModify();
758 }
759
760 /**
761 * Converts this class to a <code>java.lang.Class</code> object.
762 * Once this method is called, further modifications are not
763 * possible any more.
764 *
765 * <p>This method is equivalent to:
766 * <ul><pre>this.getClassPool().writeAsClass(this.getName())</pre></ul>
767 *
768 * <p>See the description of <code>ClassPool.writeAsClass()</code>
769 * before you use this method.
770 * This method is provided for convenience. If you need more
771 * complex functionality, you should write your own class loader.
772 *
773 * @see javassist.ClassPool#writeAsClass(String)
774 * @see javassist.ClassPool#forName(String)
775 */
776 public Class toClass()
777 throws NotFoundException, IOException, CannotCompileException {
778 return getClassPool2().writeAsClass(getName());
779 }
780
781 /**
782 * Converts this class to a class file.
783 * Once this method is called, further modifications are not
784 * possible any more.
785 *
786 * <p>This method is equivalent to:
787 * <ul><pre>this.getClassPool().write(this.getName())</pre></ul>
788 *
789 * @see javassist.ClassPool#write(String)
790 */
791 public byte[] toBytecode()
792 throws NotFoundException, IOException, CannotCompileException {
793 return getClassPool2().write(getName());
794 }
795
796 /**
797 * Writes a class file represented by this <code>CtClass</code>
798 * object in the current directory.
799 * Once this method is called, further modifications are not
800 * possible any more.
801 *
802 * <p>This method is equivalent to:
803 * <ul><pre>this.getClassPool().writeFile(this.getName())</pre></ul>
804 *
805 * @see javassist.ClassPool#writeFile(String)
806 */
807 public void writeFile()
808 throws NotFoundException, IOException, CannotCompileException {
809 getClassPool2().writeFile(getName());
810 }
811
812 private ClassPool getClassPool2() throws CannotCompileException {
813 ClassPool cp = getClassPool();
814 if (cp == null)
815 throw new CannotCompileException(
816 "no ClassPool found. not a class?");
817 else
818 return cp;
819 }
820
821 /**
822 * Converts this class to a class file.
823 * Once this method is called, further modifications are not
824 * possible any more.
825 *
826 * <p>If this method is used to obtain a byte array representing
827 * the class file, <code>Translator.onWrite()</code> is never
828 * called on this class. <code>ClassPool.write()</code> should
829 * be used.
830 *
831 * <p>This method dose not close the output stream in the end.
832 *
833 * @param out the output stream that a class file is written to.
834 */
835 void toBytecode(DataOutputStream out)
836 throws CannotCompileException, IOException {
837 throw new CannotCompileException("not a class");
838 }
839 }
840