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 32KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  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 beta 3";
  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. * Makes a new nested class. Making a nested class modifies the
  437. * data in this <code>CtClass</code>.
  438. *
  439. * <p>The current implementation only supports a static nested class.
  440. * <code>isStatic</code> must be true.
  441. *
  442. * @param name the simple name of the nested class.
  443. * @param isStatic true if the nested class is static.
  444. */
  445. public CtClass makeNestedClass(String name, boolean isStatic) {
  446. throw new RuntimeException(getName() + " is not a class");
  447. }
  448. /**
  449. * Returns an array containing <code>CtField</code> objects
  450. * representing all the public fields of the class.
  451. * That array includes public fields inherited from the
  452. * superclasses.
  453. */
  454. public CtField[] getFields() { return new CtField[0]; }
  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. * @return null if the specified field is not found.
  464. */
  465. CtField getField2(String name) { return null; }
  466. /**
  467. * Gets all the fields declared in the class. The inherited fields
  468. * are not included.
  469. *
  470. * <p>Note: the result does not include inherited fields.
  471. */
  472. public CtField[] getDeclaredFields() { return new CtField[0]; }
  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. * Gets all the constructors and methods declared in the class.
  484. */
  485. public CtBehavior[] getDeclaredBehaviors() {
  486. return new CtBehavior[0];
  487. }
  488. /**
  489. * Returns an array containing <code>CtConstructor</code> objects
  490. * representing all the public constructors of the class.
  491. */
  492. public CtConstructor[] getConstructors() {
  493. return new CtConstructor[0];
  494. }
  495. /**
  496. * Returns the constructor with the given signature,
  497. * which is represented by a character string
  498. * called method descriptor.
  499. * For details of the method descriptor, see the JVM specification
  500. * or <code>javassist.bytecode.Descriptor</code>.
  501. *
  502. * @param desc method descriptor
  503. * @see javassist.bytecode.Descriptor
  504. */
  505. public CtConstructor getConstructor(String desc)
  506. throws NotFoundException
  507. {
  508. throw new NotFoundException("no such a constructor");
  509. }
  510. /**
  511. * Gets all the constructors declared in the class.
  512. *
  513. * @see javassist.CtConstructor
  514. */
  515. public CtConstructor[] getDeclaredConstructors() {
  516. return new CtConstructor[0];
  517. }
  518. /**
  519. * Returns a constructor receiving the specified parameters.
  520. *
  521. * @param params parameter types.
  522. */
  523. public CtConstructor getDeclaredConstructor(CtClass[] params)
  524. throws NotFoundException
  525. {
  526. String desc = Descriptor.ofConstructor(params);
  527. return getConstructor(desc);
  528. }
  529. /**
  530. * Gets the class initializer (static constructor)
  531. * declared in the class.
  532. * This method returns <code>null</code> if
  533. * no class initializer is not declared.
  534. *
  535. * @see #makeClassInitializer()
  536. * @see javassist.CtConstructor
  537. */
  538. public CtConstructor getClassInitializer() {
  539. return null;
  540. }
  541. /**
  542. * Returns an array containing <code>CtMethod</code> objects
  543. * representing all the public methods of the class.
  544. * That array includes public methods inherited from the
  545. * superclasses.
  546. */
  547. public CtMethod[] getMethods() {
  548. return new CtMethod[0];
  549. }
  550. /**
  551. * Returns the method with the given name and signature.
  552. * The returned method may be declared in a super class.
  553. * The method signature is represented by a character string
  554. * called method descriptor,
  555. * which is defined in the JVM specification.
  556. *
  557. * @param name method name
  558. * @param desc method descriptor
  559. * @see javassist.bytecode.Descriptor
  560. */
  561. public CtMethod getMethod(String name, String desc)
  562. throws NotFoundException
  563. {
  564. throw new NotFoundException(name);
  565. }
  566. /**
  567. * Gets all methods declared in the class. The inherited methods
  568. * are not included.
  569. *
  570. * @see javassist.CtMethod
  571. */
  572. public CtMethod[] getDeclaredMethods() {
  573. return new CtMethod[0];
  574. }
  575. /**
  576. * Retrieves the method with the specified name and parameter types
  577. * among the methods declared in the class.
  578. *
  579. * <p>Note: this method does not search the superclasses.
  580. *
  581. * @param name method name
  582. * @param params parameter types
  583. * @see javassist.CtMethod
  584. */
  585. public CtMethod getDeclaredMethod(String name, CtClass[] params)
  586. throws NotFoundException
  587. {
  588. throw new NotFoundException(name);
  589. }
  590. /**
  591. * Retrieves the method with the specified name among the methods
  592. * declared in the class. If there are multiple methods with
  593. * the specified name, then this method returns one of them.
  594. *
  595. * <p>Note: this method does not search the superclasses.
  596. *
  597. * @see javassist.CtMethod
  598. */
  599. public CtMethod getDeclaredMethod(String name) throws NotFoundException {
  600. throw new NotFoundException(name);
  601. }
  602. /**
  603. * Makes an empty class initializer (static constructor).
  604. * If the class already includes a class initializer,
  605. * this method returns it.
  606. *
  607. * @see #getClassInitializer()
  608. */
  609. public CtConstructor makeClassInitializer()
  610. throws CannotCompileException
  611. {
  612. throw new CannotCompileException("not a class");
  613. }
  614. /**
  615. * Adds a constructor. To add a class initializer (static constructor),
  616. * call <code>makeClassInitializer()</code>.
  617. *
  618. * @see #makeClassInitializer()
  619. */
  620. public void addConstructor(CtConstructor c)
  621. throws CannotCompileException
  622. {
  623. checkModify();
  624. }
  625. /**
  626. * Adds a method.
  627. */
  628. public void addMethod(CtMethod m) throws CannotCompileException {
  629. checkModify();
  630. }
  631. /**
  632. * Adds a field.
  633. *
  634. * <p>The <code>CtField</code> belonging to another
  635. * <code>CtClass</code> cannot be directly added to this class.
  636. * Only a field created for this class can be added.
  637. *
  638. * @see javassist.CtField#CtField(CtField,CtClass)
  639. */
  640. public void addField(CtField f) throws CannotCompileException {
  641. addField(f, (CtField.Initializer)null);
  642. }
  643. /**
  644. * Adds a field with an initial value.
  645. *
  646. * <p>The <code>CtField</code> belonging to another
  647. * <code>CtClass</code> cannot be directly added to this class.
  648. * Only a field created for this class can be added.
  649. *
  650. * <p>The initial value is given as an expression written in Java.
  651. * Any regular Java expression can be used for specifying the initial
  652. * value. The followings are examples.
  653. *
  654. * <ul><pre>
  655. * cc.addField(f, "0") // the initial value is 0.
  656. * cc.addField(f, "i + 1") // i + 1.
  657. * cc.addField(f, "new Point()"); // a Point object.
  658. * </pre></ul>
  659. *
  660. * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>.
  661. * The type of <code>f</code> is <code>CtField</code>.
  662. *
  663. * @param init an expression for the initial value.
  664. *
  665. * @see javassist.CtField.Initializer#byExpr(String)
  666. * @see javassist.CtField#CtField(CtField,CtClass)
  667. */
  668. public void addField(CtField f, String init)
  669. throws CannotCompileException
  670. {
  671. checkModify();
  672. }
  673. /**
  674. * Adds a field with an initial value.
  675. *
  676. * <p>The <code>CtField</code> belonging to another
  677. * <code>CtClass</code> cannot be directly added to this class.
  678. * Only a field created for this class can be added.
  679. *
  680. * <p>For example,
  681. *
  682. * <ul><pre>
  683. * CtClass cc = ...;
  684. * addField(new CtField(CtClass.intType, "i", cc),
  685. * CtField.Initializer.constant(1));
  686. * </pre></ul>
  687. *
  688. * <p>This code adds an <code>int</code> field named "i". The
  689. * initial value of this field is 1.
  690. *
  691. * @param init specifies the initial value of the field.
  692. *
  693. * @see javassist.CtField#CtField(CtField,CtClass)
  694. */
  695. public void addField(CtField f, CtField.Initializer init)
  696. throws CannotCompileException
  697. {
  698. checkModify();
  699. }
  700. /**
  701. * Obtains an attribute with the given name.
  702. * If that attribute is not found in the class file, this
  703. * method returns null.
  704. *
  705. * @param name attribute name
  706. */
  707. public byte[] getAttribute(String name) {
  708. return null;
  709. }
  710. /**
  711. * Adds a named attribute.
  712. * An arbitrary data (smaller than 64Kb) can be saved in the class
  713. * file. Some attribute name are reserved by the JVM.
  714. * The attributes with the non-reserved names are ignored when a
  715. * class file is loaded into the JVM.
  716. * If there is already an attribute with
  717. * the same name, this method substitutes the new one for it.
  718. *
  719. * @param name attribute name
  720. * @param data attribute value
  721. */
  722. public void setAttribute(String name, byte[] data) {
  723. checkModify();
  724. }
  725. /**
  726. * Applies the given converter to 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 converter specifies how to modify.
  732. */
  733. public void instrument(CodeConverter converter)
  734. throws CannotCompileException
  735. {
  736. checkModify();
  737. }
  738. /**
  739. * Modifies the bodies of all methods and constructors
  740. * declared in the class. This method calls <code>instrument()</code>
  741. * on every <code>CtMethod</code> and <code>CtConstructor</code> object
  742. * in the class.
  743. *
  744. * @param editor specifies how to modify.
  745. */
  746. public void instrument(ExprEditor editor)
  747. throws CannotCompileException
  748. {
  749. checkModify();
  750. }
  751. /**
  752. * Converts this class to a <code>java.lang.Class</code> object.
  753. * Once this method is called, further modifications are not
  754. * allowed any more.
  755. * To load the class, this method uses the context class loader
  756. * of the current thread. If the program is running on some application
  757. * server, the context class loader might be inappropriate to load the
  758. * class.
  759. *
  760. * <p>This method is provided for convenience. If you need more
  761. * complex functionality, you should write your own class loader.
  762. *
  763. * @see #toClass(java.lang.ClassLoader)
  764. */
  765. public Class toClass()
  766. throws CannotCompileException
  767. {
  768. return toClass(Thread.currentThread().getContextClassLoader());
  769. }
  770. /**
  771. * Converts this class to a <code>java.lang.Class</code> object.
  772. * Once this method is called, further modifications are not allowed
  773. * any more.
  774. *
  775. * <p>The class file represented by this <code>CtClass</code> is
  776. * loaded by the given class loader to construct a
  777. * <code>java.lang.Class</code> object. Since a private method
  778. * on the class loader is invoked through the reflection API,
  779. * the caller must have permissions to do that.
  780. *
  781. * <p>This method is provided for convenience. If you need more
  782. * complex functionality, you should write your own class loader.
  783. *
  784. * @param loader the class loader used to load this class.
  785. */
  786. public Class toClass(ClassLoader loader)
  787. throws CannotCompileException
  788. {
  789. try {
  790. byte[] b = toBytecode();
  791. Class cl = Class.forName("java.lang.ClassLoader");
  792. java.lang.reflect.Method method
  793. = cl.getDeclaredMethod("defineClass",
  794. new Class[] { String.class, byte[].class,
  795. int.class, int.class });
  796. method.setAccessible(true);
  797. Object[] args = new Object[] { getName(), b, new Integer(0),
  798. new Integer(b.length)};
  799. Class clazz = (Class)method.invoke(loader, args);
  800. method.setAccessible(false);
  801. return clazz;
  802. }
  803. catch (RuntimeException e) {
  804. throw e;
  805. }
  806. catch (java.lang.reflect.InvocationTargetException e) {
  807. throw new CannotCompileException(e.getTargetException());
  808. }
  809. catch (Exception e) {
  810. throw new CannotCompileException(e);
  811. }
  812. }
  813. /**
  814. * Removes this <code>CtClass</code> from the <code>ClassPool</code>.
  815. * After this method is called, any method cannot be called on the
  816. * removed <code>CtClass</code> object.
  817. *
  818. * <p>If needed,
  819. * the <code>ClassPool</code> will read the class file again
  820. * and constructs another <code>CtClass</code> object representing
  821. * the same class.
  822. */
  823. public void detach() {
  824. ClassPool cp = getClassPool();
  825. CtClass obj = cp.removeCached(getName());
  826. if (obj != this)
  827. cp.cacheCtClass(getName(), obj);
  828. }
  829. /**
  830. * Converts this class to a class file.
  831. * Once this method is called, further modifications are not
  832. * possible any more.
  833. *
  834. * @return the contents of the class file.
  835. */
  836. public byte[] toBytecode()
  837. throws IOException, CannotCompileException
  838. {
  839. ByteArrayOutputStream barray = new ByteArrayOutputStream();
  840. DataOutputStream out = new DataOutputStream(barray);
  841. try {
  842. toBytecode(out);
  843. }
  844. finally {
  845. out.close();
  846. }
  847. return barray.toByteArray();
  848. }
  849. /**
  850. * Writes a class file represented by this <code>CtClass</code>
  851. * object in the current directory.
  852. * Once this method is called, further modifications are not
  853. * possible any more.
  854. */
  855. public void writeFile()
  856. throws NotFoundException, IOException, CannotCompileException
  857. {
  858. writeFile(".");
  859. }
  860. /**
  861. * Writes a class file represented by this <code>CtClass</code>
  862. * object on a local disk.
  863. * Once this method is called, further modifications are not
  864. * possible any more.
  865. *
  866. * @param directoryName it must end without a directory separator.
  867. */
  868. public void writeFile(String directoryName)
  869. throws NotFoundException, CannotCompileException, IOException
  870. {
  871. String classname = getName();
  872. String filename = directoryName + File.separatorChar
  873. + classname.replace('.', File.separatorChar) + ".class";
  874. int pos = filename.lastIndexOf(File.separatorChar);
  875. if (pos > 0) {
  876. String dir = filename.substring(0, pos);
  877. if (!dir.equals("."))
  878. new File(dir).mkdirs();
  879. }
  880. DataOutputStream out
  881. = new DataOutputStream(new BufferedOutputStream(
  882. new DelayedFileOutputStream(filename)));
  883. try {
  884. toBytecode(out);
  885. }
  886. finally {
  887. out.close();
  888. }
  889. }
  890. static class DelayedFileOutputStream extends OutputStream {
  891. private FileOutputStream file;
  892. private String filename;
  893. DelayedFileOutputStream(String name) {
  894. file = null;
  895. filename = name;
  896. }
  897. private void init() throws IOException {
  898. if (file == null)
  899. file = new FileOutputStream(filename);
  900. }
  901. public void write(int b) throws IOException {
  902. init();
  903. file.write(b);
  904. }
  905. public void write(byte[] b) throws IOException {
  906. init();
  907. file.write(b);
  908. }
  909. public void write(byte[] b, int off, int len) throws IOException {
  910. init();
  911. file.write(b, off, len);
  912. }
  913. public void flush() throws IOException {
  914. init();
  915. file.flush();
  916. }
  917. public void close() throws IOException {
  918. init();
  919. file.close();
  920. }
  921. }
  922. /**
  923. * Converts this class to a class file.
  924. * Once this method is called, further modifications are not
  925. * possible any more.
  926. *
  927. * <p>This method dose not close the output stream in the end.
  928. *
  929. * @param out the output stream that a class file is written to.
  930. */
  931. public void toBytecode(DataOutputStream out)
  932. throws CannotCompileException, IOException
  933. {
  934. throw new CannotCompileException("not a class");
  935. }
  936. }