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.

ClassPool.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  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 java.net.URL;
  18. import java.util.Hashtable;
  19. /**
  20. * A driver class for controlling bytecode editing with Javassist.
  21. * It manages where a class file is obtained and how it is modified.
  22. *
  23. * <p>A <code>ClassPool</code> object can be regarded as a container
  24. * of <code>CtClass</code> objects. It reads class files on demand
  25. * from various
  26. * sources represented by <code>ClassPath</code> and create
  27. * <code>CtClass</code> objects representing those class files.
  28. *
  29. * <p>A <code>CtClass</code>
  30. * object contained in a <code>ClassPool</code> is written to an
  31. * output stream (or a file) if <code>write()</code>
  32. * (or <code>writeFile()</code>) is called on the
  33. * <code>ClassPool</code>.
  34. * <code>write()</code> is typically called by a class loader,
  35. * which obtains the bytecode image to be loaded.
  36. *
  37. * <p>The users can modify <code>CtClass</code> objects
  38. * before those objects are written out.
  39. * To obtain a reference
  40. * to a <code>CtClass</code> object contained in a
  41. * <code>ClassPool</code>, <code>get()</code> should be
  42. * called on the <code>ClassPool</code>. If a <code>CtClass</code>
  43. * object is modified, then the modification is reflected on the resulting
  44. * class file returned by <code>write()</code> in <code>ClassPool</code>.
  45. *
  46. * <p>In summary,
  47. *
  48. * <ul>
  49. * <li><code>get()</code> returns a reference to a <code>CtClass</code>
  50. * object contained in a <code>ClassPool</code>.
  51. *
  52. * <li><code>write()</code> translates a <code>CtClass</code>
  53. * object contained in a <code>ClassPool</code> into a class file
  54. * and writes it to an output stream.
  55. * </ul>
  56. *
  57. * <p>The users can add a listener object receiving an event from a
  58. * <code>ClassPool</code>. An event occurs when a listener is
  59. * added to a <code>ClassPool</code> and when <code>write()</code>
  60. * is called on a <code>ClassPool</code> (not when <code>get()</code>
  61. * is called!). The listener class
  62. * must implement <code>Translator</code>. A typical listener object
  63. * is used for modifying a <code>CtClass</code> object <i>on demand</i>
  64. * when it is written to an output stream.
  65. *
  66. * <p>The implementation of this class is thread-safe.
  67. *
  68. * <p><b>Memory consumption memo:</b>
  69. *
  70. * <p><code>ClassPool</code> objects hold all the <code>CtClass</code>es
  71. * that have been created so that the consistency among modified classes
  72. * can be guaranteed. Thus if a large number of <code>CtClass</code>es
  73. * are processed, the <code>ClassPool</code> will consume a huge amount
  74. * of memory. To avoid this, multiple <code>ClassPool</code> objects
  75. * must be used. Note that <code>getDefault()</code> is a singleton
  76. * factory.
  77. *
  78. *
  79. * @see javassist.CtClass
  80. * @see javassist.ClassPath
  81. * @see javassist.Translator
  82. */
  83. public class ClassPool extends AbsClassPool {
  84. protected AbsClassPool source;
  85. protected ClassPool parent;
  86. protected Translator translator;
  87. protected Hashtable classes; // should be synchronous
  88. /**
  89. * Table of registered cflow variables.
  90. */
  91. private Hashtable cflow = null; // should be synchronous.
  92. /**
  93. * Creates a class pool.
  94. *
  95. * @param src the source of class files. If it is null,
  96. * the class search path is initially null.
  97. * @param p the parent of this class pool.
  98. * @see javassist.ClassPool#getDefault()
  99. */
  100. public ClassPool(ClassPool p) {
  101. this(new ClassPoolTail(), p);
  102. }
  103. ClassPool(AbsClassPool src, ClassPool parent) {
  104. this.classes = new Hashtable();
  105. this.source = src;
  106. this.parent = parent;
  107. if (parent == null) {
  108. // if this has no parent, it must include primitive types
  109. // even if this.source is not a ClassPoolTail.
  110. CtClass[] pt = CtClass.primitiveTypes;
  111. for (int i = 0; i < pt.length; ++i)
  112. classes.put(pt[i].getName(), pt[i]);
  113. }
  114. this.translator = null;
  115. this.cflow = null;
  116. }
  117. /**
  118. * Inserts a new translator at the head of the translator chain.
  119. *
  120. * @param trans a new translator associated with this class pool.
  121. * @throws RuntimeException if trans.start() throws an exception.
  122. */
  123. public void insertTranslator(Translator trans) throws RuntimeException {
  124. ClassPool next = new ClassPool(source, parent);
  125. next.translator = trans;
  126. source = next;
  127. try {
  128. trans.start(next);
  129. }
  130. catch (Exception e) {
  131. throw new RuntimeException(
  132. "Translator.start() throws an exception: "
  133. + e.toString());
  134. }
  135. }
  136. /**
  137. * Returns the default class pool.
  138. * The returned object is always identical since this method is
  139. * a singleton factory.
  140. *
  141. * <p>The default class pool searches the system search path,
  142. * which usually includes the platform library, extension
  143. * libraries, and the search path specified by the
  144. * <code>-classpath</code> option or the <code>CLASSPATH</code>
  145. * environment variable.
  146. *
  147. * <p>When this method is called for the first time, the default
  148. * class pool is created with the following code snippet:
  149. *
  150. * <ul><code>ClassPool cp = new ClassPool(null);
  151. * cp.appendSystemPath();
  152. * </code></ul>
  153. *
  154. * @param t null or the translator linked to the class pool.
  155. */
  156. public static synchronized ClassPool getDefault() {
  157. if (defaultPool == null) {
  158. defaultPool = new ClassPool(null);
  159. defaultPool.appendSystemPath();
  160. }
  161. return defaultPool;
  162. }
  163. private static ClassPool defaultPool = null;
  164. /**
  165. * Provide a hook so that subclasses can do their own
  166. * caching of classes
  167. *
  168. * @see #removeCached(String)
  169. */
  170. protected CtClass getCached(String classname)
  171. {
  172. return (CtClass)classes.get(classname);
  173. }
  174. /**
  175. * Provide a hook so that subclasses can do their own
  176. * caching of classes
  177. *
  178. * @see #getCached(String)
  179. */
  180. protected void removeCached(String classname)
  181. {
  182. classes.remove(classname);
  183. }
  184. /**
  185. * Returns the class search path.
  186. */
  187. public String toString() {
  188. return source.toString();
  189. }
  190. /**
  191. * Records a name that never exists.
  192. * For example, a package name can be recorded by this method.
  193. * This would improve execution performance
  194. * since <code>get()</code> does not search the class path at all
  195. * if the given name is an invalid name recorded by this method.
  196. * Note that searching the class path takes relatively long time.
  197. *
  198. * @param name a class name (separeted by dot).
  199. */
  200. public void recordInvalidClassName(String name) {
  201. source.recordInvalidClassName(name);
  202. }
  203. /**
  204. * Returns the <code>Translator</code> object associated with
  205. * this <code>ClassPool</code>.
  206. *
  207. * @deprecated
  208. */
  209. Translator getTranslator() { return translator; }
  210. /**
  211. * Records the <code>$cflow</code> variable for the field specified
  212. * by <code>cname</code> and <code>fname</code>.
  213. *
  214. * @param name variable name
  215. * @param cname class name
  216. * @param fname field name
  217. */
  218. void recordCflow(String name, String cname, String fname) {
  219. if (cflow == null)
  220. cflow = new Hashtable();
  221. cflow.put(name, new Object[] { cname, fname });
  222. }
  223. /**
  224. * Undocumented method. Do not use; internal-use only.
  225. *
  226. * @param name the name of <code>$cflow</code> variable
  227. */
  228. public Object[] lookupCflow(String name) {
  229. if (cflow == null)
  230. cflow = new Hashtable();
  231. return (Object[])cflow.get(name);
  232. }
  233. /**
  234. * Writes a class file specified with <code>classname</code>
  235. * in the current directory.
  236. * It never calls <code>onWrite()</code> on a translator.
  237. * It is provided for debugging.
  238. *
  239. * @param classname the name of the class written on a local disk.
  240. */
  241. public void debugWriteFile(String classname)
  242. throws NotFoundException, CannotCompileException, IOException
  243. {
  244. debugWriteFile(classname, ".");
  245. }
  246. /**
  247. * Writes a class file specified with <code>classname</code>.
  248. * It never calls <code>onWrite()</code> on a translator.
  249. * It is provided for debugging.
  250. *
  251. * @param classname the name of the class written on a local disk.
  252. * @param directoryName it must end without a directory separator.
  253. */
  254. public void debugWriteFile(String classname, String directoryName)
  255. throws NotFoundException, CannotCompileException, IOException
  256. {
  257. writeFile(classname, directoryName, false);
  258. }
  259. /* void writeFile(CtClass) should not be defined since writeFile()
  260. * may be called on the class pool that does not contain the given
  261. * CtClass object.
  262. */
  263. /**
  264. * Writes a class file specified with <code>classname</code>
  265. * in the current directory.
  266. * It calls <code>onWrite()</code> on a translator.
  267. *
  268. * @param classname the name of the class written on a local disk.
  269. */
  270. public void writeFile(String classname)
  271. throws NotFoundException, CannotCompileException, IOException
  272. {
  273. writeFile(classname, ".");
  274. }
  275. /**
  276. * Writes a class file specified with <code>classname</code>
  277. * on a local disk.
  278. * It calls <code>onWrite()</code> on a translator.
  279. *
  280. * @param classname the name of the class written on a local disk.
  281. * @param directoryName it must end without a directory separator.
  282. */
  283. public void writeFile(String classname, String directoryName)
  284. throws NotFoundException, CannotCompileException, IOException
  285. {
  286. writeFile(classname, directoryName, true);
  287. }
  288. private void writeFile(String classname, String directoryName,
  289. boolean callback)
  290. throws NotFoundException, CannotCompileException, IOException
  291. {
  292. String filename = directoryName + File.separatorChar
  293. + classname.replace('.', File.separatorChar) + ".class";
  294. int pos = filename.lastIndexOf(File.separatorChar);
  295. if (pos > 0) {
  296. String dir = filename.substring(0, pos);
  297. if (!dir.equals("."))
  298. new File(dir).mkdirs();
  299. }
  300. DataOutputStream out
  301. = new DataOutputStream(new BufferedOutputStream(
  302. new DelayedFileOutputStream(filename)));
  303. write(classname, out, callback);
  304. out.close();
  305. }
  306. static class DelayedFileOutputStream extends OutputStream {
  307. private FileOutputStream file;
  308. private String filename;
  309. DelayedFileOutputStream(String name) {
  310. file = null;
  311. filename = name;
  312. }
  313. private void init() throws IOException {
  314. if (file == null)
  315. file = new FileOutputStream(filename);
  316. }
  317. public void write(int b) throws IOException {
  318. init();
  319. file.write(b);
  320. }
  321. public void write(byte[] b) throws IOException {
  322. init();
  323. file.write(b);
  324. }
  325. public void write(byte[] b, int off, int len) throws IOException {
  326. init();
  327. file.write(b, off, len);
  328. }
  329. public void flush() throws IOException {
  330. init();
  331. file.flush();
  332. }
  333. public void close() throws IOException {
  334. init();
  335. file.close();
  336. }
  337. }
  338. /**
  339. * A simple class loader used by <code>writeAsClass()</code>
  340. * in <code>ClassPool</code>.
  341. * This class loader is provided for convenience. If you need more
  342. * complex functionality, you should write your own class loader.
  343. *
  344. * @see ClassPool#writeAsClass(String)
  345. * @see CtClass#toClass()
  346. */
  347. public static class SimpleLoader extends ClassLoader {
  348. /**
  349. * Loads a class.
  350. *
  351. * @param name the fully qualified class name.
  352. * @param classfile the class file.
  353. * @throws ClassFormatError if the class file is wrong.
  354. */
  355. public Class loadClass(String name, byte[] classfile)
  356. throws ClassFormatError
  357. {
  358. Class c = defineClass(name, classfile, 0, classfile.length);
  359. resolveClass(c);
  360. return c;
  361. }
  362. };
  363. private static SimpleLoader classLoader = new SimpleLoader();
  364. /**
  365. * Returns a <code>java.lang.Class</code> object that has been loaded
  366. * by <code>writeAsClass()</code>. Such an object cannot be
  367. * obtained by <code>java.lang.Class.forName()</code> because it has
  368. * been loaded by an internal class loader of Javassist.
  369. *
  370. * @see #writeAsClass(String)
  371. * @see javassist.CtClass#toClass()
  372. */
  373. public static Class forName(String name) throws ClassNotFoundException {
  374. return classLoader.loadClass(name);
  375. }
  376. /**
  377. * Returns a <code>java.lang.Class</code> object.
  378. * It calls <code>write()</code> to obtain a class file and then
  379. * loads the obtained class file into the JVM. The returned
  380. * <code>Class</code> object represents the loaded class.
  381. *
  382. * <p>This method is provided for convenience. If you need more
  383. * complex functionality, you should write your own class loader.
  384. *
  385. * <p>To load a class file, this method uses an internal class loader,
  386. * which is an instance of <code>ClassPool.SimpleLoader</code>.
  387. * Thus, that class file is not loaded by the system class loader,
  388. * which should have loaded this <code>ClassPool</code> class.
  389. * The internal class loader
  390. * loads only the classes explicitly specified by this method
  391. * <code>writeAsClass()</code>. The other classes are loaded
  392. * by the parent class loader (the sytem class loader) by delegation.
  393. *
  394. * <p>For example,
  395. *
  396. * <ul><pre>class Line { Point p1, p2; }</pre></ul>
  397. *
  398. * <p>If the class <code>Line</code> is loaded by the internal class
  399. * loader and the class <code>Point</code> has not been loaded yet,
  400. * then the class <code>Point</code> that the class <code>Line</code>
  401. * refers to is loaded by the parent class loader. There is no
  402. * chance of modifying the definition of <code>Point</code> with
  403. * Javassist.
  404. *
  405. * <p>The internal class loader is shared among all the instances
  406. * of <code>ClassPool</code>.
  407. *
  408. * @param classname a fully-qualified class name.
  409. *
  410. * @see #forName(String)
  411. * @see javassist.CtClass#toClass()
  412. * @see javassist.Loader
  413. */
  414. public Class writeAsClass(String classname)
  415. throws NotFoundException, IOException, CannotCompileException
  416. {
  417. try {
  418. return classLoader.loadClass(classname, write(classname));
  419. }
  420. catch (ClassFormatError e) {
  421. throw new CannotCompileException(e, classname);
  422. }
  423. }
  424. /**
  425. * Returns a byte array representing the class file.
  426. * It calls <code>onWrite()</code> on a translator.
  427. *
  428. * @param classname a fully-qualified class name.
  429. */
  430. public byte[] write(String classname)
  431. throws NotFoundException, IOException, CannotCompileException
  432. {
  433. ByteArrayOutputStream barray = new ByteArrayOutputStream();
  434. DataOutputStream out = new DataOutputStream(barray);
  435. try {
  436. write(classname, out, true);
  437. }
  438. finally {
  439. out.close();
  440. }
  441. return barray.toByteArray();
  442. }
  443. /**
  444. * Writes a class file specified by <code>classname</code>
  445. * to a given output stream.
  446. * It calls <code>onWrite()</code> on a translator.
  447. *
  448. * <p>This method does not close the output stream in the end.
  449. *
  450. * @param classname a fully-qualified class name.
  451. * @param out an output stream
  452. */
  453. public void write(String classname, DataOutputStream out)
  454. throws NotFoundException, CannotCompileException, IOException
  455. {
  456. write(classname, out, true);
  457. }
  458. private void write(String classname, DataOutputStream out,
  459. boolean callback)
  460. throws NotFoundException, CannotCompileException, IOException
  461. {
  462. if (!write0(classname, out, callback))
  463. throw new NotFoundException(classname);
  464. }
  465. boolean write0(String classname, DataOutputStream out, boolean callback)
  466. throws NotFoundException, CannotCompileException, IOException
  467. {
  468. // first, delegate to the parent.
  469. if (parent != null && parent.write0(classname, out, callback))
  470. return true;
  471. CtClass clazz = (CtClass)getCached(classname);
  472. if (callback && translator != null
  473. && (clazz == null || !clazz.isFrozen())) {
  474. translator.onWrite(this, classname);
  475. // The CtClass object might be overwritten.
  476. clazz = (CtClass)getCached(classname);
  477. }
  478. if (clazz == null || !clazz.isModified()) {
  479. if (clazz != null)
  480. clazz.freeze();
  481. return source.write0(classname, out, callback);
  482. }
  483. else {
  484. clazz.toBytecode(out);
  485. return true;
  486. }
  487. }
  488. /* for CtClassType.getClassFile2(). Don't delegate to the parent.
  489. */
  490. byte[] readSource(String classname)
  491. throws NotFoundException, IOException, CannotCompileException
  492. {
  493. return source.readSource(classname);
  494. }
  495. /*
  496. * Is invoked by CtClassType.setName(). Don't delegate to the parent.
  497. */
  498. synchronized void classNameChanged(String oldname, CtClass clazz) {
  499. CtClass c = (CtClass)getCached(oldname);
  500. if (c == clazz) // must check this equation.
  501. removeCached(oldname); // see getAndRename().
  502. String newName = clazz.getName();
  503. checkNotFrozen(newName);
  504. classes.put(newName, clazz);
  505. }
  506. /*
  507. * Is invoked by CtClassType.setName() and methods in this class.
  508. * This method throws an exception if the class is already frozen or
  509. * if this class pool cannot edit the class since it is in a parent
  510. * class pool.
  511. */
  512. void checkNotFrozen(String classname) throws RuntimeException {
  513. CtClass c;
  514. if (parent != null) {
  515. try {
  516. c = parent.get0(classname);
  517. }
  518. catch (NotFoundException e) { // some error happens.
  519. throw new RuntimeException(e.toString());
  520. }
  521. if (c != null)
  522. throw new RuntimeException(classname
  523. + " is in a parent ClassPool. Use the parent.");
  524. }
  525. c = getCached(classname);
  526. if (c != null && c.isFrozen())
  527. throw new RuntimeException(classname +
  528. ": frozen class (cannot edit)");
  529. }
  530. /**
  531. * Reads a class file and constructs a <code>CtClass</code>
  532. * object with a new name.
  533. * This method is useful if you want to generate a new class as a copy
  534. * of another class (except the class name). For example,
  535. *
  536. * <ul><pre>
  537. * getAndRename("Point", "Pair")
  538. * </pre></ul>
  539. *
  540. * returns a <code>CtClass</code> object representing <code>Pair</code>
  541. * class. The definition of <code>Pair</code> is the same as that of
  542. * <code>Point</code> class except the class name since <code>Pair</code>
  543. * is defined by reading <code>Point.class</code>.
  544. *
  545. * @param orgName the original (fully-qualified) class name
  546. * @param newName the new class name
  547. */
  548. public CtClass getAndRename(String orgName, String newName)
  549. throws NotFoundException
  550. {
  551. CtClass clazz = null;
  552. if (parent != null)
  553. clazz = parent.get1(orgName);
  554. if (clazz == null)
  555. clazz = get1(orgName);
  556. if (clazz == null)
  557. throw new NotFoundException(orgName);
  558. clazz.setName(newName); // indirectly calls
  559. // classNameChanged() in this class
  560. return clazz;
  561. }
  562. /**
  563. * Reads a class file from the source and returns a reference
  564. * to the <code>CtClass</code>
  565. * object representing that class file. If that class file has been
  566. * already read, this method returns a reference to the
  567. * <code>CtClass</code> created when that class file was read at the
  568. * first time.
  569. *
  570. * <p>If <code>classname</code> ends with "[]", then this method
  571. * returns a <code>CtClass</code> object for that array type.
  572. *
  573. * <p>To obtain an inner class, use "$" instead of "." for separating
  574. * the enclosing class name and the inner class name.
  575. *
  576. * @param classname a fully-qualified class name.
  577. */
  578. public CtClass get(String classname) throws NotFoundException {
  579. CtClass clazz = get0(classname);
  580. if (clazz == null)
  581. throw new NotFoundException(classname);
  582. else
  583. return clazz;
  584. }
  585. /**
  586. * @return null if the class could not be found.
  587. */
  588. private synchronized CtClass get0(String classname)
  589. throws NotFoundException
  590. {
  591. CtClass clazz;
  592. if (parent != null) {
  593. clazz = parent.get0(classname);
  594. if (clazz != null)
  595. return clazz;
  596. }
  597. clazz = getCached(classname);
  598. if (clazz == null) {
  599. clazz = get1(classname);
  600. if (clazz != null)
  601. classes.put(classname, clazz);
  602. }
  603. return clazz;
  604. }
  605. private CtClass get1(String classname) throws NotFoundException {
  606. if (classname.endsWith("[]")) {
  607. String base = classname.substring(0, classname.indexOf('['));
  608. if (getCached(base) == null && find(base) == null)
  609. return null;
  610. else
  611. return new CtArray(classname, this);
  612. }
  613. else
  614. if (find(classname) == null)
  615. return null;
  616. else
  617. return new CtClassType(classname, this);
  618. }
  619. /**
  620. * Obtains the URL of the class file specified by classname.
  621. * This method does not delegate to the parent pool.
  622. *
  623. * @param classname a fully-qualified class name.
  624. * @return null if the class file could not be found.
  625. */
  626. URL find(String classname) {
  627. return source.find(classname);
  628. }
  629. /**
  630. * Reads class files from the source and returns an array of
  631. * <code>CtClass</code>
  632. * objects representing those class files.
  633. *
  634. * <p>If an element of <code>classnames</code> ends with "[]",
  635. * then this method
  636. * returns a <code>CtClass</code> object for that array type.
  637. *
  638. * @param classnames an array of fully-qualified class name.
  639. */
  640. public CtClass[] get(String[] classnames) throws NotFoundException {
  641. if (classnames == null)
  642. return new CtClass[0];
  643. int num = classnames.length;
  644. CtClass[] result = new CtClass[num];
  645. for (int i = 0; i < num; ++i)
  646. result[i] = get(classnames[i]);
  647. return result;
  648. }
  649. /**
  650. * Reads a class file and obtains a compile-time method.
  651. *
  652. * @param classname the class name
  653. * @param methodname the method name
  654. *
  655. * @see CtClass#getDeclaredMethod(String)
  656. */
  657. public CtMethod getMethod(String classname, String methodname)
  658. throws NotFoundException
  659. {
  660. CtClass c = get(classname);
  661. return c.getDeclaredMethod(methodname);
  662. }
  663. /**
  664. * Creates a new class (or interface) from the given class file.
  665. * If there already exists a class with the same name, the new class
  666. * overwrites that previous class.
  667. *
  668. * <p>This method is used for creating a <code>CtClass</code> object
  669. * directly from a class file. The qualified class name is obtained
  670. * from the class file; you do not have to explicitly give the name.
  671. *
  672. * @param classfile class file.
  673. * @exception RuntimeException if there is a frozen class with the
  674. * the same name.
  675. * @see javassist.ByteArrayClassPath
  676. */
  677. public CtClass makeClass(InputStream classfile)
  678. throws IOException, RuntimeException
  679. {
  680. CtClass clazz = new CtClassType(classfile, this);
  681. clazz.checkModify();
  682. String classname = clazz.getName();
  683. checkNotFrozen(classname);
  684. classes.put(classname, clazz);
  685. return clazz;
  686. }
  687. /**
  688. * Creates a new public class.
  689. * If there already exists a class with the same name, the new class
  690. * overwrites that previous class.
  691. *
  692. * @param classname a fully-qualified class name.
  693. * @exception RuntimeException if the existing class is frozen.
  694. */
  695. public CtClass makeClass(String classname) throws RuntimeException {
  696. return makeClass(classname, null);
  697. }
  698. /**
  699. * Creates a new public class.
  700. * If there already exists a class/interface with the same name,
  701. * the new class overwrites that previous class.
  702. *
  703. * @param classname a fully-qualified class name.
  704. * @param superclass the super class.
  705. * @exception RuntimeException if the existing class is frozen.
  706. */
  707. public synchronized CtClass makeClass(String classname, CtClass superclass)
  708. throws RuntimeException
  709. {
  710. checkNotFrozen(classname);
  711. CtClass clazz = new CtNewClass(classname, this, false, superclass);
  712. classes.put(classname, clazz);
  713. return clazz;
  714. }
  715. /**
  716. * Creates a new public interface.
  717. * If there already exists a class/interface with the same name,
  718. * the new interface overwrites that previous one.
  719. *
  720. * @param name a fully-qualified interface name.
  721. * @exception RuntimeException if the existing interface is frozen.
  722. */
  723. public CtClass makeInterface(String name) throws RuntimeException {
  724. return makeInterface(name, null);
  725. }
  726. /**
  727. * Creates a new public interface.
  728. * If there already exists a class/interface with the same name,
  729. * the new interface overwrites that previous one.
  730. *
  731. * @param name a fully-qualified interface name.
  732. * @param superclass the super interface.
  733. * @exception RuntimeException if the existing interface is frozen.
  734. */
  735. public synchronized CtClass makeInterface(String name, CtClass superclass)
  736. throws RuntimeException
  737. {
  738. checkNotFrozen(name);
  739. CtClass clazz = new CtNewClass(name, this, true, superclass);
  740. classes.put(name, clazz);
  741. return clazz;
  742. }
  743. /**
  744. * Appends the system search path to the end of the
  745. * search path. The system search path
  746. * usually includes the platform library, extension
  747. * libraries, and the search path specified by the
  748. * <code>-classpath</code> option or the <code>CLASSPATH</code>
  749. * environment variable.
  750. *
  751. * @return the appended class path.
  752. */
  753. public ClassPath appendSystemPath() {
  754. return source.appendSystemPath();
  755. }
  756. /**
  757. * Insert a <code>ClassPath</code> object at the head of the
  758. * search path.
  759. *
  760. * @return the inserted class path.
  761. *
  762. * @see javassist.ClassPath
  763. * @see javassist.URLClassPath
  764. * @see javassist.ByteArrayClassPath
  765. */
  766. public ClassPath insertClassPath(ClassPath cp) {
  767. return source.insertClassPath(cp);
  768. }
  769. /**
  770. * Appends a <code>ClassPath</code> object to the end of the
  771. * search path.
  772. *
  773. * @return the appended class path.
  774. *
  775. * @see javassist.ClassPath
  776. * @see javassist.URLClassPath
  777. * @see javassist.ByteArrayClassPath
  778. */
  779. public ClassPath appendClassPath(ClassPath cp) {
  780. return source.appendClassPath(cp);
  781. }
  782. /**
  783. * Inserts a directory or a jar (or zip) file at the head of the
  784. * search path.
  785. *
  786. * @param pathname the path name of the directory or jar file.
  787. * It must not end with a path separator ("/").
  788. * @return the inserted class path.
  789. * @exception NotFoundException if the jar file is not found.
  790. */
  791. public ClassPath insertClassPath(String pathname)
  792. throws NotFoundException
  793. {
  794. return source.insertClassPath(pathname);
  795. }
  796. /**
  797. * Appends a directory or a jar (or zip) file to the end of the
  798. * search path.
  799. *
  800. * @param pathname the path name of the directory or jar file.
  801. * It must not end with a path separator ("/").
  802. * @return the appended class path.
  803. * @exception NotFoundException if the jar file is not found.
  804. */
  805. public ClassPath appendClassPath(String pathname)
  806. throws NotFoundException
  807. {
  808. return source.appendClassPath(pathname);
  809. }
  810. /**
  811. * Detatches the <code>ClassPath</code> object from the search path.
  812. * The detached <code>ClassPath</code> object cannot be added
  813. * to the pathagain.
  814. */
  815. public void removeClassPath(ClassPath cp) {
  816. source.removeClassPath(cp);
  817. }
  818. /**
  819. * Appends directories and jar files for search.
  820. *
  821. * <p>The elements of the given path list must be separated by colons
  822. * in Unix or semi-colons in Windows.
  823. *
  824. * @param pathlist a (semi)colon-separated list of
  825. * the path names of directories and jar files.
  826. * The directory name must not end with a path
  827. * separator ("/").
  828. *
  829. * @exception NotFoundException if a jar file is not found.
  830. */
  831. public void appendPathList(String pathlist) throws NotFoundException {
  832. char sep = File.pathSeparatorChar;
  833. int i = 0;
  834. for (;;) {
  835. int j = pathlist.indexOf(sep, i);
  836. if (j < 0) {
  837. appendClassPath(pathlist.substring(i));
  838. break;
  839. }
  840. else {
  841. appendClassPath(pathlist.substring(i, j));
  842. i = j + 1;
  843. }
  844. }
  845. }
  846. }