You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CtClass.java 31KB

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