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

AntClassLoader.java 53 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495
  1. /*
  2. * Copyright 2000-2005 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant;
  18. import java.io.ByteArrayOutputStream;
  19. import java.io.File;
  20. import java.io.FileInputStream;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.InputStreamReader;
  24. import java.io.Reader;
  25. import java.lang.reflect.Constructor;
  26. import java.net.MalformedURLException;
  27. import java.net.URL;
  28. import java.net.URLDecoder;
  29. import java.util.Collections;
  30. import java.util.Enumeration;
  31. import java.util.HashMap;
  32. import java.util.Hashtable;
  33. import java.util.Map;
  34. import java.util.StringTokenizer;
  35. import java.util.Vector;
  36. import java.util.jar.Attributes;
  37. import java.util.jar.Attributes.Name;
  38. import java.util.jar.JarFile;
  39. import java.util.jar.Manifest;
  40. import java.util.zip.ZipEntry;
  41. import java.util.zip.ZipFile;
  42. import org.apache.tools.ant.types.Path;
  43. import org.apache.tools.ant.util.CollectionUtils;
  44. import org.apache.tools.ant.util.FileUtils;
  45. import org.apache.tools.ant.util.JavaEnvUtils;
  46. import org.apache.tools.ant.util.LoaderUtils;
  47. import org.apache.tools.ant.launch.Locator;
  48. /**
  49. * Used to load classes within ant with a different classpath from
  50. * that used to start ant. Note that it is possible to force a class
  51. * into this loader even when that class is on the system classpath by
  52. * using the forceLoadClass method. Any subsequent classes loaded by that
  53. * class will then use this loader rather than the system class loader.
  54. *
  55. */
  56. public class AntClassLoader extends ClassLoader implements SubBuildListener {
  57. private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  58. /**
  59. * An enumeration of all resources of a given name found within the
  60. * classpath of this class loader. This enumeration is used by the
  61. * ClassLoader.findResources method, which is in
  62. * turn used by the ClassLoader.getResources method.
  63. *
  64. * @see AntClassLoader#findResources(String)
  65. * @see java.lang.ClassLoader#getResources(String)
  66. */
  67. private class ResourceEnumeration implements Enumeration {
  68. /**
  69. * The name of the resource being searched for.
  70. */
  71. private String resourceName;
  72. /**
  73. * The index of the next classpath element to search.
  74. */
  75. private int pathElementsIndex;
  76. /**
  77. * The URL of the next resource to return in the enumeration. If this
  78. * field is <code>null</code> then the enumeration has been completed,
  79. * i.e., there are no more elements to return.
  80. */
  81. private URL nextResource;
  82. /**
  83. * Constructs a new enumeration of resources of the given name found
  84. * within this class loader's classpath.
  85. *
  86. * @param name the name of the resource to search for.
  87. */
  88. ResourceEnumeration(String name) {
  89. this.resourceName = name;
  90. this.pathElementsIndex = 0;
  91. findNextResource();
  92. }
  93. /**
  94. * Indicates whether there are more elements in the enumeration to
  95. * return.
  96. *
  97. * @return <code>true</code> if there are more elements in the
  98. * enumeration; <code>false</code> otherwise.
  99. */
  100. public boolean hasMoreElements() {
  101. return (this.nextResource != null);
  102. }
  103. /**
  104. * Returns the next resource in the enumeration.
  105. *
  106. * @return the next resource in the enumeration
  107. */
  108. public Object nextElement() {
  109. URL ret = this.nextResource;
  110. findNextResource();
  111. return ret;
  112. }
  113. /**
  114. * Locates the next resource of the correct name in the classpath and
  115. * sets <code>nextResource</code> to the URL of that resource. If no
  116. * more resources can be found, <code>nextResource</code> is set to
  117. * <code>null</code>.
  118. */
  119. private void findNextResource() {
  120. URL url = null;
  121. while ((pathElementsIndex < pathComponents.size())
  122. && (url == null)) {
  123. try {
  124. File pathComponent
  125. = (File) pathComponents.elementAt(pathElementsIndex);
  126. url = getResourceURL(pathComponent, this.resourceName);
  127. pathElementsIndex++;
  128. } catch (BuildException e) {
  129. // ignore path elements which are not valid relative to the
  130. // project
  131. }
  132. }
  133. this.nextResource = url;
  134. }
  135. }
  136. /**
  137. * The size of buffers to be used in this classloader.
  138. */
  139. private static final int BUFFER_SIZE = 8192;
  140. /**
  141. * Number of array elements in a test array of strings
  142. */
  143. private static final int NUMBER_OF_STRINGS = 256;
  144. /**
  145. * The components of the classpath that the classloader searches
  146. * for classes.
  147. */
  148. private Vector pathComponents = new Vector();
  149. /**
  150. * The project to which this class loader belongs.
  151. */
  152. private Project project;
  153. /**
  154. * Indicates whether the parent class loader should be
  155. * consulted before trying to load with this class loader.
  156. */
  157. private boolean parentFirst = true;
  158. /**
  159. * These are the package roots that are to be loaded by the parent class
  160. * loader regardless of whether the parent class loader is being searched
  161. * first or not.
  162. */
  163. private Vector systemPackages = new Vector();
  164. /**
  165. * These are the package roots that are to be loaded by this class loader
  166. * regardless of whether the parent class loader is being searched first
  167. * or not.
  168. */
  169. private Vector loaderPackages = new Vector();
  170. /**
  171. * Whether or not this classloader will ignore the base
  172. * classloader if it can't find a class.
  173. *
  174. * @see #setIsolated(boolean)
  175. */
  176. private boolean ignoreBase = false;
  177. /**
  178. * The parent class loader, if one is given or can be determined.
  179. */
  180. private ClassLoader parent = null;
  181. /**
  182. * A hashtable of zip files opened by the classloader (File to ZipFile).
  183. */
  184. private Hashtable zipFiles = new Hashtable();
  185. /** Static map of jar file/time to manifiest class-path entries */
  186. private static Map/*<String,String>*/ pathMap = Collections.synchronizedMap(new HashMap());
  187. /**
  188. * The context loader saved when setting the thread's current
  189. * context loader.
  190. */
  191. private ClassLoader savedContextLoader = null;
  192. /**
  193. * Whether or not the context loader is currently saved.
  194. */
  195. private boolean isContextLoaderSaved = false;
  196. /**
  197. * Create an Ant Class Loader
  198. */
  199. public AntClassLoader() {
  200. setParent(null);
  201. }
  202. /**
  203. * Creates a classloader for the given project using the classpath given.
  204. *
  205. * @param project The project to which this classloader is to belong.
  206. * Must not be <code>null</code>.
  207. * @param classpath The classpath to use to load the classes. This
  208. * is combined with the system classpath in a manner
  209. * determined by the value of ${build.sysclasspath}.
  210. * May be <code>null</code>, in which case no path
  211. * elements are set up to start with.
  212. */
  213. public AntClassLoader(Project project, Path classpath) {
  214. setParent(null);
  215. setProject(project);
  216. setClassPath(classpath);
  217. }
  218. /**
  219. * Creates a classloader for the given project using the classpath given.
  220. *
  221. * @param parent The parent classloader to which unsatisfied loading
  222. * attempts are delegated. May be <code>null</code>,
  223. * in which case the classloader which loaded this
  224. * class is used as the parent.
  225. * @param project The project to which this classloader is to belong.
  226. * Must not be <code>null</code>.
  227. * @param classpath the classpath to use to load the classes.
  228. * May be <code>null</code>, in which case no path
  229. * elements are set up to start with.
  230. * @param parentFirst If <code>true</code>, indicates that the parent
  231. * classloader should be consulted before trying to
  232. * load the a class through this loader.
  233. */
  234. public AntClassLoader(ClassLoader parent, Project project, Path classpath,
  235. boolean parentFirst) {
  236. this(project, classpath);
  237. if (parent != null) {
  238. setParent(parent);
  239. }
  240. setParentFirst(parentFirst);
  241. addJavaLibraries();
  242. }
  243. /**
  244. * Creates a classloader for the given project using the classpath given.
  245. *
  246. * @param project The project to which this classloader is to belong.
  247. * Must not be <code>null</code>.
  248. * @param classpath The classpath to use to load the classes. May be
  249. * <code>null</code>, in which case no path
  250. * elements are set up to start with.
  251. * @param parentFirst If <code>true</code>, indicates that the parent
  252. * classloader should be consulted before trying to
  253. * load the a class through this loader.
  254. */
  255. public AntClassLoader(Project project, Path classpath,
  256. boolean parentFirst) {
  257. this(null, project, classpath, parentFirst);
  258. }
  259. /**
  260. * Creates an empty class loader. The classloader should be configured
  261. * with path elements to specify where the loader is to look for
  262. * classes.
  263. *
  264. * @param parent The parent classloader to which unsatisfied loading
  265. * attempts are delegated. May be <code>null</code>,
  266. * in which case the classloader which loaded this
  267. * class is used as the parent.
  268. * @param parentFirst If <code>true</code>, indicates that the parent
  269. * classloader should be consulted before trying to
  270. * load the a class through this loader.
  271. */
  272. public AntClassLoader(ClassLoader parent, boolean parentFirst) {
  273. setParent(parent);
  274. project = null;
  275. this.parentFirst = parentFirst;
  276. }
  277. /**
  278. * Set the project associated with this class loader
  279. *
  280. * @param project the project instance
  281. */
  282. public void setProject(Project project) {
  283. this.project = project;
  284. if (project != null) {
  285. project.addBuildListener(this);
  286. }
  287. }
  288. /**
  289. * Set the classpath to search for classes to load. This should not be
  290. * changed once the classloader starts to server classes
  291. *
  292. * @param classpath the search classpath consisting of directories and
  293. * jar/zip files.
  294. */
  295. public void setClassPath(Path classpath) {
  296. pathComponents.removeAllElements();
  297. if (classpath != null) {
  298. Path actualClasspath = classpath.concatSystemClasspath("ignore");
  299. String[] pathElements = actualClasspath.list();
  300. for (int i = 0; i < pathElements.length; ++i) {
  301. try {
  302. addPathElement(pathElements[i]);
  303. } catch (BuildException e) {
  304. // ignore path elements which are invalid
  305. // relative to the project
  306. }
  307. }
  308. }
  309. }
  310. /**
  311. * Set the parent for this class loader. This is the class loader to which
  312. * this class loader will delegate to load classes
  313. *
  314. * @param parent the parent class loader.
  315. */
  316. public void setParent(ClassLoader parent) {
  317. if (parent == null) {
  318. this.parent = AntClassLoader.class.getClassLoader();
  319. } else {
  320. this.parent = parent;
  321. }
  322. }
  323. /**
  324. * Control whether class lookup is delegated to the parent loader first
  325. * or after this loader. Use with extreme caution. Setting this to
  326. * false violates the class loader hierarchy and can lead to Linkage errors
  327. *
  328. * @param parentFirst if true, delegate initial class search to the parent
  329. * classloader.
  330. */
  331. public void setParentFirst(boolean parentFirst) {
  332. this.parentFirst = parentFirst;
  333. }
  334. /**
  335. * Logs a message through the project object if one has been provided.
  336. *
  337. * @param message The message to log.
  338. * Should not be <code>null</code>.
  339. *
  340. * @param priority The logging priority of the message.
  341. */
  342. protected void log(String message, int priority) {
  343. if (project != null) {
  344. project.log(message, priority);
  345. }
  346. // else {
  347. // System.out.println(message);
  348. // }
  349. }
  350. /**
  351. * Sets the current thread's context loader to this classloader, storing
  352. * the current loader value for later resetting.
  353. */
  354. public void setThreadContextLoader() {
  355. if (isContextLoaderSaved) {
  356. throw new BuildException("Context loader has not been reset");
  357. }
  358. if (LoaderUtils.isContextLoaderAvailable()) {
  359. savedContextLoader = LoaderUtils.getContextClassLoader();
  360. ClassLoader loader = this;
  361. if (project != null
  362. && "only".equals(project.getProperty("build.sysclasspath"))) {
  363. loader = this.getClass().getClassLoader();
  364. }
  365. LoaderUtils.setContextClassLoader(loader);
  366. isContextLoaderSaved = true;
  367. }
  368. }
  369. /**
  370. * Resets the current thread's context loader to its original value.
  371. */
  372. public void resetThreadContextLoader() {
  373. if (LoaderUtils.isContextLoaderAvailable()
  374. && isContextLoaderSaved) {
  375. LoaderUtils.setContextClassLoader(savedContextLoader);
  376. savedContextLoader = null;
  377. isContextLoaderSaved = false;
  378. }
  379. }
  380. /**
  381. * Adds an element to the classpath to be searched.
  382. *
  383. * @param pathElement The path element to add. Must not be
  384. * <code>null</code>.
  385. *
  386. * @exception BuildException if the given path element cannot be resolved
  387. * against the project.
  388. */
  389. public void addPathElement(String pathElement) throws BuildException {
  390. File pathComponent
  391. = project != null ? project.resolveFile(pathElement)
  392. : new File(pathElement);
  393. try {
  394. addPathFile(pathComponent);
  395. } catch (IOException e) {
  396. throw new BuildException(e);
  397. }
  398. }
  399. /**
  400. * Add a file to the path.
  401. * Reads the manifest, if available, and adds any additional class path jars
  402. * specified in the manifest.
  403. *
  404. * @param pathComponent the file which is to be added to the path for
  405. * this class loader
  406. *
  407. * @throws IOException if data needed from the file cannot be read.
  408. */
  409. protected void addPathFile(File pathComponent) throws IOException {
  410. pathComponents.addElement(pathComponent);
  411. if (pathComponent.isDirectory()) {
  412. return;
  413. }
  414. String absPathPlusTimeAndLength =
  415. pathComponent.getAbsolutePath() + pathComponent.lastModified() + "-"
  416. + pathComponent.length();
  417. String classpath = (String) pathMap.get(absPathPlusTimeAndLength);
  418. if (classpath == null) {
  419. ZipFile jarFile = null;
  420. InputStream manifestStream = null;
  421. try {
  422. jarFile = new ZipFile(pathComponent);
  423. manifestStream
  424. = jarFile.getInputStream(new ZipEntry("META-INF/MANIFEST.MF"));
  425. if (manifestStream == null) {
  426. return;
  427. }
  428. Reader manifestReader
  429. = new InputStreamReader(manifestStream, "UTF-8");
  430. org.apache.tools.ant.taskdefs.Manifest manifest
  431. = new org.apache.tools.ant.taskdefs.Manifest(manifestReader);
  432. classpath
  433. = manifest.getMainSection().getAttributeValue("Class-Path");
  434. } catch (org.apache.tools.ant.taskdefs.ManifestException e) {
  435. // ignore
  436. } finally {
  437. if (manifestStream != null) {
  438. manifestStream.close();
  439. }
  440. if (jarFile != null) {
  441. jarFile.close();
  442. }
  443. }
  444. if (classpath == null) {
  445. classpath = "";
  446. }
  447. pathMap.put(absPathPlusTimeAndLength, classpath);
  448. }
  449. if (!"".equals(classpath)) {
  450. URL baseURL = FILE_UTILS.getFileURL(pathComponent);
  451. StringTokenizer st = new StringTokenizer(classpath);
  452. while (st.hasMoreTokens()) {
  453. String classpathElement = st.nextToken();
  454. URL libraryURL = new URL(baseURL, classpathElement);
  455. if (!libraryURL.getProtocol().equals("file")) {
  456. log("Skipping jar library " + classpathElement
  457. + " since only relative URLs are supported by this"
  458. + " loader", Project.MSG_VERBOSE);
  459. continue;
  460. }
  461. String decodedPath = Locator.decodeUri(libraryURL.getFile());
  462. File libraryFile = new File(decodedPath);
  463. if (libraryFile.exists() && !isInPath(libraryFile)) {
  464. addPathFile(libraryFile);
  465. }
  466. }
  467. }
  468. }
  469. /**
  470. * Returns the classpath this classloader will consult.
  471. *
  472. * @return the classpath used for this classloader, with elements
  473. * separated by the path separator for the system.
  474. */
  475. public String getClasspath() {
  476. StringBuffer sb = new StringBuffer();
  477. boolean firstPass = true;
  478. Enumeration componentEnum = pathComponents.elements();
  479. while (componentEnum.hasMoreElements()) {
  480. if (!firstPass) {
  481. sb.append(System.getProperty("path.separator"));
  482. } else {
  483. firstPass = false;
  484. }
  485. sb.append(((File) componentEnum.nextElement()).getAbsolutePath());
  486. }
  487. return sb.toString();
  488. }
  489. /**
  490. * Sets whether this classloader should run in isolated mode. In
  491. * isolated mode, classes not found on the given classpath will
  492. * not be referred to the parent class loader but will cause a
  493. * ClassNotFoundException.
  494. *
  495. * @param isolated Whether or not this classloader should run in
  496. * isolated mode.
  497. */
  498. public synchronized void setIsolated(boolean isolated) {
  499. ignoreBase = isolated;
  500. }
  501. /**
  502. * Forces initialization of a class in a JDK 1.1 compatible, albeit hacky
  503. * way.
  504. *
  505. * @param theClass The class to initialize.
  506. * Must not be <code>null</code>.
  507. *
  508. * @deprecated use Class.forName with initialize=true instead.
  509. */
  510. public static void initializeClass(Class theClass) {
  511. // ***HACK*** We ask the VM to create an instance
  512. // by voluntarily providing illegal arguments to force
  513. // the VM to run the class' static initializer, while
  514. // at the same time not running a valid constructor.
  515. final Constructor[] cons = theClass.getDeclaredConstructors();
  516. //At least one constructor is guaranteed to be there, but check anyway.
  517. if (cons != null) {
  518. if (cons.length > 0 && cons[0] != null) {
  519. final String[] strs = new String[NUMBER_OF_STRINGS];
  520. try {
  521. cons[0].newInstance((Object[]) strs);
  522. // Expecting an exception to be thrown by this call:
  523. // IllegalArgumentException: wrong number of Arguments
  524. } catch (Exception e) {
  525. // Ignore - we are interested only in the side
  526. // effect - that of getting the static initializers
  527. // invoked. As we do not want to call a valid
  528. // constructor to get this side effect, an
  529. // attempt is made to call a hopefully
  530. // invalid constructor - come on, nobody
  531. // would have a constructor that takes in
  532. // 256 String arguments ;-)
  533. // (In fact, they can't - according to JVM spec
  534. // section 4.10, the number of method parameters is limited
  535. // to 255 by the definition of a method descriptor.
  536. // Constructors count as methods here.)
  537. }
  538. }
  539. }
  540. }
  541. /**
  542. * Adds a package root to the list of packages which must be loaded on the
  543. * parent loader.
  544. *
  545. * All subpackages are also included.
  546. *
  547. * @param packageRoot The root of all packages to be included.
  548. * Should not be <code>null</code>.
  549. */
  550. public void addSystemPackageRoot(String packageRoot) {
  551. systemPackages.addElement(packageRoot
  552. + (packageRoot.endsWith(".") ? "" : "."));
  553. }
  554. /**
  555. * Adds a package root to the list of packages which must be loaded using
  556. * this loader.
  557. *
  558. * All subpackages are also included.
  559. *
  560. * @param packageRoot The root of all packages to be included.
  561. * Should not be <code>null</code>.
  562. */
  563. public void addLoaderPackageRoot(String packageRoot) {
  564. loaderPackages.addElement(packageRoot
  565. + (packageRoot.endsWith(".") ? "" : "."));
  566. }
  567. /**
  568. * Loads a class through this class loader even if that class is available
  569. * on the parent classpath.
  570. *
  571. * This ensures that any classes which are loaded by the returned class
  572. * will use this classloader.
  573. *
  574. * @param classname The name of the class to be loaded.
  575. * Must not be <code>null</code>.
  576. *
  577. * @return the required Class object
  578. *
  579. * @exception ClassNotFoundException if the requested class does not exist
  580. * on this loader's classpath.
  581. */
  582. public Class forceLoadClass(String classname)
  583. throws ClassNotFoundException {
  584. log("force loading " + classname, Project.MSG_DEBUG);
  585. Class theClass = findLoadedClass(classname);
  586. if (theClass == null) {
  587. theClass = findClass(classname);
  588. }
  589. return theClass;
  590. }
  591. /**
  592. * Loads a class through this class loader but defer to the parent class
  593. * loader.
  594. *
  595. * This ensures that instances of the returned class will be compatible
  596. * with instances which have already been loaded on the parent
  597. * loader.
  598. *
  599. * @param classname The name of the class to be loaded.
  600. * Must not be <code>null</code>.
  601. *
  602. * @return the required Class object
  603. *
  604. * @exception ClassNotFoundException if the requested class does not exist
  605. * on this loader's classpath.
  606. */
  607. public Class forceLoadSystemClass(String classname)
  608. throws ClassNotFoundException {
  609. log("force system loading " + classname, Project.MSG_DEBUG);
  610. Class theClass = findLoadedClass(classname);
  611. if (theClass == null) {
  612. theClass = findBaseClass(classname);
  613. }
  614. return theClass;
  615. }
  616. /**
  617. * Returns a stream to read the requested resource name.
  618. *
  619. * @param name The name of the resource for which a stream is required.
  620. * Must not be <code>null</code>.
  621. *
  622. * @return a stream to the required resource or <code>null</code> if the
  623. * resource cannot be found on the loader's classpath.
  624. */
  625. public InputStream getResourceAsStream(String name) {
  626. InputStream resourceStream = null;
  627. if (isParentFirst(name)) {
  628. resourceStream = loadBaseResource(name);
  629. if (resourceStream != null) {
  630. log("ResourceStream for " + name
  631. + " loaded from parent loader", Project.MSG_DEBUG);
  632. } else {
  633. resourceStream = loadResource(name);
  634. if (resourceStream != null) {
  635. log("ResourceStream for " + name
  636. + " loaded from ant loader", Project.MSG_DEBUG);
  637. }
  638. }
  639. } else {
  640. resourceStream = loadResource(name);
  641. if (resourceStream != null) {
  642. log("ResourceStream for " + name
  643. + " loaded from ant loader", Project.MSG_DEBUG);
  644. } else {
  645. resourceStream = loadBaseResource(name);
  646. if (resourceStream != null) {
  647. log("ResourceStream for " + name
  648. + " loaded from parent loader", Project.MSG_DEBUG);
  649. }
  650. }
  651. }
  652. if (resourceStream == null) {
  653. log("Couldn't load ResourceStream for " + name,
  654. Project.MSG_DEBUG);
  655. }
  656. return resourceStream;
  657. }
  658. /**
  659. * Returns a stream to read the requested resource name from this loader.
  660. *
  661. * @param name The name of the resource for which a stream is required.
  662. * Must not be <code>null</code>.
  663. *
  664. * @return a stream to the required resource or <code>null</code> if
  665. * the resource cannot be found on the loader's classpath.
  666. */
  667. private InputStream loadResource(String name) {
  668. // we need to search the components of the path to see if we can
  669. // find the class we want.
  670. InputStream stream = null;
  671. Enumeration e = pathComponents.elements();
  672. while (e.hasMoreElements() && stream == null) {
  673. File pathComponent = (File) e.nextElement();
  674. stream = getResourceStream(pathComponent, name);
  675. }
  676. return stream;
  677. }
  678. /**
  679. * Finds a system resource (which should be loaded from the parent
  680. * classloader).
  681. *
  682. * @param name The name of the system resource to load.
  683. * Must not be <code>null</code>.
  684. *
  685. * @return a stream to the named resource, or <code>null</code> if
  686. * the resource cannot be found.
  687. */
  688. private InputStream loadBaseResource(String name) {
  689. if (parent == null) {
  690. return getSystemResourceAsStream(name);
  691. } else {
  692. return parent.getResourceAsStream(name);
  693. }
  694. }
  695. /**
  696. * Returns an inputstream to a given resource in the given file which may
  697. * either be a directory or a zip file.
  698. *
  699. * @param file the file (directory or jar) in which to search for the
  700. * resource. Must not be <code>null</code>.
  701. * @param resourceName The name of the resource for which a stream is
  702. * required. Must not be <code>null</code>.
  703. *
  704. * @return a stream to the required resource or <code>null</code> if
  705. * the resource cannot be found in the given file.
  706. */
  707. private InputStream getResourceStream(File file, String resourceName) {
  708. try {
  709. if (!file.exists()) {
  710. return null;
  711. }
  712. if (file.isDirectory()) {
  713. File resource = new File(file, resourceName);
  714. if (resource.exists()) {
  715. return new FileInputStream(resource);
  716. }
  717. } else {
  718. // is the zip file in the cache
  719. ZipFile zipFile = (ZipFile) zipFiles.get(file);
  720. if (zipFile == null) {
  721. zipFile = new ZipFile(file);
  722. zipFiles.put(file, zipFile);
  723. }
  724. ZipEntry entry = zipFile.getEntry(resourceName);
  725. if (entry != null) {
  726. return zipFile.getInputStream(entry);
  727. }
  728. }
  729. } catch (Exception e) {
  730. log("Ignoring Exception " + e.getClass().getName()
  731. + ": " + e.getMessage() + " reading resource " + resourceName
  732. + " from " + file, Project.MSG_VERBOSE);
  733. }
  734. return null;
  735. }
  736. /**
  737. * Tests whether or not the parent classloader should be checked for
  738. * a resource before this one. If the resource matches both the
  739. * "use parent classloader first" and the "use this classloader first"
  740. * lists, the latter takes priority.
  741. *
  742. * @param resourceName The name of the resource to check.
  743. * Must not be <code>null</code>.
  744. *
  745. * @return whether or not the parent classloader should be checked for a
  746. * resource before this one is.
  747. */
  748. private boolean isParentFirst(String resourceName) {
  749. // default to the global setting and then see
  750. // if this class belongs to a package which has been
  751. // designated to use a specific loader first
  752. // (this one or the parent one)
  753. // XXX - shouldn't this always return false in isolated mode?
  754. boolean useParentFirst = parentFirst;
  755. for (Enumeration e = systemPackages.elements(); e.hasMoreElements();) {
  756. String packageName = (String) e.nextElement();
  757. if (resourceName.startsWith(packageName)) {
  758. useParentFirst = true;
  759. break;
  760. }
  761. }
  762. for (Enumeration e = loaderPackages.elements(); e.hasMoreElements();) {
  763. String packageName = (String) e.nextElement();
  764. if (resourceName.startsWith(packageName)) {
  765. useParentFirst = false;
  766. break;
  767. }
  768. }
  769. return useParentFirst;
  770. }
  771. /**
  772. * Finds the resource with the given name. A resource is
  773. * some data (images, audio, text, etc) that can be accessed by class
  774. * code in a way that is independent of the location of the code.
  775. *
  776. * @param name The name of the resource for which a stream is required.
  777. * Must not be <code>null</code>.
  778. *
  779. * @return a URL for reading the resource, or <code>null</code> if the
  780. * resource could not be found or the caller doesn't have
  781. * adequate privileges to get the resource.
  782. */
  783. public URL getResource(String name) {
  784. // we need to search the components of the path to see if
  785. // we can find the class we want.
  786. URL url = null;
  787. if (isParentFirst(name)) {
  788. url = (parent == null) ? super.getResource(name)
  789. : parent.getResource(name);
  790. }
  791. if (url != null) {
  792. log("Resource " + name + " loaded from parent loader",
  793. Project.MSG_DEBUG);
  794. } else {
  795. // try and load from this loader if the parent either didn't find
  796. // it or wasn't consulted.
  797. Enumeration e = pathComponents.elements();
  798. while (e.hasMoreElements() && url == null) {
  799. File pathComponent = (File) e.nextElement();
  800. url = getResourceURL(pathComponent, name);
  801. if (url != null) {
  802. log("Resource " + name
  803. + " loaded from ant loader",
  804. Project.MSG_DEBUG);
  805. }
  806. }
  807. }
  808. if (url == null && !isParentFirst(name)) {
  809. // this loader was first but it didn't find it - try the parent
  810. url = (parent == null) ? super.getResource(name)
  811. : parent.getResource(name);
  812. if (url != null) {
  813. log("Resource " + name + " loaded from parent loader",
  814. Project.MSG_DEBUG);
  815. }
  816. }
  817. if (url == null) {
  818. log("Couldn't load Resource " + name, Project.MSG_DEBUG);
  819. }
  820. return url;
  821. }
  822. /**
  823. * Returns an enumeration of URLs representing all the resources with the
  824. * given name by searching the class loader's classpath.
  825. *
  826. * @param name The resource name to search for.
  827. * Must not be <code>null</code>.
  828. * @return an enumeration of URLs for the resources
  829. * @exception IOException if I/O errors occurs (can't happen)
  830. */
  831. protected Enumeration/*<URL>*/ findResources(String name) throws IOException {
  832. Enumeration/*<URL>*/ mine = new ResourceEnumeration(name);
  833. Enumeration/*<URL>*/ base;
  834. if (parent != null && parent != getParent()) {
  835. // Delegate to the parent:
  836. base = parent.getResources(name);
  837. // Note: could cause overlaps in case ClassLoader.this.parent has matches.
  838. } else {
  839. // ClassLoader.this.parent is already delegated to from
  840. // ClassLoader.getResources, no need:
  841. base = new CollectionUtils.EmptyEnumeration();
  842. }
  843. if (isParentFirst(name)) {
  844. // Normal case.
  845. return CollectionUtils.append(base, mine);
  846. } else {
  847. // Inverted.
  848. return CollectionUtils.append(mine, base);
  849. }
  850. }
  851. /**
  852. * Returns the URL of a given resource in the given file which may
  853. * either be a directory or a zip file.
  854. *
  855. * @param file The file (directory or jar) in which to search for
  856. * the resource. Must not be <code>null</code>.
  857. * @param resourceName The name of the resource for which a stream
  858. * is required. Must not be <code>null</code>.
  859. *
  860. * @return a stream to the required resource or <code>null</code> if the
  861. * resource cannot be found in the given file object.
  862. */
  863. protected URL getResourceURL(File file, String resourceName) {
  864. try {
  865. if (!file.exists()) {
  866. return null;
  867. }
  868. if (file.isDirectory()) {
  869. File resource = new File(file, resourceName);
  870. if (resource.exists()) {
  871. try {
  872. return FILE_UTILS.getFileURL(resource);
  873. } catch (MalformedURLException ex) {
  874. return null;
  875. }
  876. }
  877. } else {
  878. ZipFile zipFile = (ZipFile) zipFiles.get(file);
  879. if (zipFile == null) {
  880. zipFile = new ZipFile(file);
  881. zipFiles.put(file, zipFile);
  882. }
  883. ZipEntry entry = zipFile.getEntry(resourceName);
  884. if (entry != null) {
  885. try {
  886. return new URL("jar:" + FILE_UTILS.getFileURL(file)
  887. + "!/" + entry);
  888. } catch (MalformedURLException ex) {
  889. return null;
  890. }
  891. }
  892. }
  893. } catch (Exception e) {
  894. e.printStackTrace();
  895. }
  896. return null;
  897. }
  898. /**
  899. * Loads a class with this class loader.
  900. *
  901. * This class attempts to load the class in an order determined by whether
  902. * or not the class matches the system/loader package lists, with the
  903. * loader package list taking priority. If the classloader is in isolated
  904. * mode, failure to load the class in this loader will result in a
  905. * ClassNotFoundException.
  906. *
  907. * @param classname The name of the class to be loaded.
  908. * Must not be <code>null</code>.
  909. * @param resolve <code>true</code> if all classes upon which this class
  910. * depends are to be loaded.
  911. *
  912. * @return the required Class object
  913. *
  914. * @exception ClassNotFoundException if the requested class does not exist
  915. * on the system classpath (when not in isolated mode) or this loader's
  916. * classpath.
  917. */
  918. protected synchronized Class loadClass(String classname, boolean resolve)
  919. throws ClassNotFoundException {
  920. // 'sync' is needed - otherwise 2 threads can load the same class
  921. // twice, resulting in LinkageError: duplicated class definition.
  922. // findLoadedClass avoids that, but without sync it won't work.
  923. Class theClass = findLoadedClass(classname);
  924. if (theClass != null) {
  925. return theClass;
  926. }
  927. if (isParentFirst(classname)) {
  928. try {
  929. theClass = findBaseClass(classname);
  930. log("Class " + classname + " loaded from parent loader "
  931. + "(parentFirst)", Project.MSG_DEBUG);
  932. } catch (ClassNotFoundException cnfe) {
  933. theClass = findClass(classname);
  934. log("Class " + classname + " loaded from ant loader "
  935. + "(parentFirst)", Project.MSG_DEBUG);
  936. }
  937. } else {
  938. try {
  939. theClass = findClass(classname);
  940. log("Class " + classname + " loaded from ant loader",
  941. Project.MSG_DEBUG);
  942. } catch (ClassNotFoundException cnfe) {
  943. if (ignoreBase) {
  944. throw cnfe;
  945. }
  946. theClass = findBaseClass(classname);
  947. log("Class " + classname + " loaded from parent loader",
  948. Project.MSG_DEBUG);
  949. }
  950. }
  951. if (resolve) {
  952. resolveClass(theClass);
  953. }
  954. return theClass;
  955. }
  956. /**
  957. * Converts the class dot notation to a filesystem equivalent for
  958. * searching purposes.
  959. *
  960. * @param classname The class name in dot format (eg java.lang.Integer).
  961. * Must not be <code>null</code>.
  962. *
  963. * @return the classname in filesystem format (eg java/lang/Integer.class)
  964. */
  965. private String getClassFilename(String classname) {
  966. return classname.replace('.', '/') + ".class";
  967. }
  968. /**
  969. * Define a class given its bytes
  970. *
  971. * @param container the container from which the class data has been read
  972. * may be a directory or a jar/zip file.
  973. *
  974. * @param classData the bytecode data for the class
  975. * @param classname the name of the class
  976. *
  977. * @return the Class instance created from the given data
  978. *
  979. * @throws IOException if the class data cannot be read.
  980. */
  981. protected Class defineClassFromData(File container, byte[] classData,
  982. String classname) throws IOException {
  983. definePackage(container, classname);
  984. // XXX should instead make a new ProtectionDomain with a CodeSource
  985. // corresponding to container.toURI().toURL() and the same
  986. // PermissionCollection as Project.class.protectionDomain had
  987. return defineClass(classname, classData, 0, classData.length,
  988. Project.class.getProtectionDomain());
  989. }
  990. /**
  991. * Define the package information associated with a class.
  992. *
  993. * @param container the file containing the class definition.
  994. * @param className the class name of for which the package information
  995. * is to be determined.
  996. *
  997. * @exception IOException if the package information cannot be read from the
  998. * container.
  999. */
  1000. protected void definePackage(File container, String className)
  1001. throws IOException {
  1002. int classIndex = className.lastIndexOf('.');
  1003. if (classIndex == -1) {
  1004. return;
  1005. }
  1006. String packageName = className.substring(0, classIndex);
  1007. if (getPackage(packageName) != null) {
  1008. // already defined
  1009. return;
  1010. }
  1011. // define the package now
  1012. Manifest manifest = getJarManifest(container);
  1013. if (manifest == null) {
  1014. definePackage(packageName, null, null, null, null, null,
  1015. null, null);
  1016. } else {
  1017. definePackage(container, packageName, manifest);
  1018. }
  1019. }
  1020. /**
  1021. * Get the manifest from the given jar, if it is indeed a jar and it has a
  1022. * manifest
  1023. *
  1024. * @param container the File from which a manifest is required.
  1025. *
  1026. * @return the jar's manifest or null is the container is not a jar or it
  1027. * has no manifest.
  1028. *
  1029. * @exception IOException if the manifest cannot be read.
  1030. */
  1031. private Manifest getJarManifest(File container) throws IOException {
  1032. if (container.isDirectory()) {
  1033. return null;
  1034. }
  1035. JarFile jarFile = null;
  1036. try {
  1037. jarFile = new JarFile(container);
  1038. return jarFile.getManifest();
  1039. } finally {
  1040. if (jarFile != null) {
  1041. jarFile.close();
  1042. }
  1043. }
  1044. }
  1045. /**
  1046. * Define the package information when the class comes from a
  1047. * jar with a manifest
  1048. *
  1049. * @param container the jar file containing the manifest
  1050. * @param packageName the name of the package being defined.
  1051. * @param manifest the jar's manifest
  1052. */
  1053. protected void definePackage(File container, String packageName,
  1054. Manifest manifest) {
  1055. String sectionName = packageName.replace('.', '/') + "/";
  1056. String specificationTitle = null;
  1057. String specificationVendor = null;
  1058. String specificationVersion = null;
  1059. String implementationTitle = null;
  1060. String implementationVendor = null;
  1061. String implementationVersion = null;
  1062. String sealedString = null;
  1063. URL sealBase = null;
  1064. Attributes sectionAttributes = manifest.getAttributes(sectionName);
  1065. if (sectionAttributes != null) {
  1066. specificationTitle
  1067. = sectionAttributes.getValue(Name.SPECIFICATION_TITLE);
  1068. specificationVendor
  1069. = sectionAttributes.getValue(Name.SPECIFICATION_VENDOR);
  1070. specificationVersion
  1071. = sectionAttributes.getValue(Name.SPECIFICATION_VERSION);
  1072. implementationTitle
  1073. = sectionAttributes.getValue(Name.IMPLEMENTATION_TITLE);
  1074. implementationVendor
  1075. = sectionAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
  1076. implementationVersion
  1077. = sectionAttributes.getValue(Name.IMPLEMENTATION_VERSION);
  1078. sealedString
  1079. = sectionAttributes.getValue(Name.SEALED);
  1080. }
  1081. Attributes mainAttributes = manifest.getMainAttributes();
  1082. if (mainAttributes != null) {
  1083. if (specificationTitle == null) {
  1084. specificationTitle
  1085. = mainAttributes.getValue(Name.SPECIFICATION_TITLE);
  1086. }
  1087. if (specificationVendor == null) {
  1088. specificationVendor
  1089. = mainAttributes.getValue(Name.SPECIFICATION_VENDOR);
  1090. }
  1091. if (specificationVersion == null) {
  1092. specificationVersion
  1093. = mainAttributes.getValue(Name.SPECIFICATION_VERSION);
  1094. }
  1095. if (implementationTitle == null) {
  1096. implementationTitle
  1097. = mainAttributes.getValue(Name.IMPLEMENTATION_TITLE);
  1098. }
  1099. if (implementationVendor == null) {
  1100. implementationVendor
  1101. = mainAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
  1102. }
  1103. if (implementationVersion == null) {
  1104. implementationVersion
  1105. = mainAttributes.getValue(Name.IMPLEMENTATION_VERSION);
  1106. }
  1107. if (sealedString == null) {
  1108. sealedString
  1109. = mainAttributes.getValue(Name.SEALED);
  1110. }
  1111. }
  1112. if (sealedString != null && sealedString.equalsIgnoreCase("true")) {
  1113. try {
  1114. // XXX should be using FileUtils!
  1115. sealBase = new URL("file:" + container.getPath());
  1116. } catch (MalformedURLException e) {
  1117. // ignore
  1118. }
  1119. }
  1120. definePackage(packageName, specificationTitle, specificationVersion,
  1121. specificationVendor, implementationTitle,
  1122. implementationVersion, implementationVendor, sealBase);
  1123. }
  1124. /**
  1125. * Reads a class definition from a stream.
  1126. *
  1127. * @param stream The stream from which the class is to be read.
  1128. * Must not be <code>null</code>.
  1129. * @param classname The name of the class in the stream.
  1130. * Must not be <code>null</code>.
  1131. * @param container the file or directory containing the class.
  1132. *
  1133. * @return the Class object read from the stream.
  1134. *
  1135. * @exception IOException if there is a problem reading the class from the
  1136. * stream.
  1137. * @exception SecurityException if there is a security problem while
  1138. * reading the class from the stream.
  1139. */
  1140. private Class getClassFromStream(InputStream stream, String classname,
  1141. File container)
  1142. throws IOException, SecurityException {
  1143. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  1144. int bytesRead = -1;
  1145. byte[] buffer = new byte[BUFFER_SIZE];
  1146. while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) {
  1147. baos.write(buffer, 0, bytesRead);
  1148. }
  1149. byte[] classData = baos.toByteArray();
  1150. return defineClassFromData(container, classData, classname);
  1151. }
  1152. /**
  1153. * Searches for and load a class on the classpath of this class loader.
  1154. *
  1155. * @param name The name of the class to be loaded. Must not be
  1156. * <code>null</code>.
  1157. *
  1158. * @return the required Class object
  1159. *
  1160. * @exception ClassNotFoundException if the requested class does not exist
  1161. * on this loader's classpath.
  1162. */
  1163. public Class findClass(String name) throws ClassNotFoundException {
  1164. log("Finding class " + name, Project.MSG_DEBUG);
  1165. return findClassInComponents(name);
  1166. }
  1167. /**
  1168. * Indicate if the given file is in this loader's path
  1169. *
  1170. * @param component the file which is to be checked
  1171. *
  1172. * @return true if the file is in the class path
  1173. */
  1174. protected boolean isInPath(File component) {
  1175. for (Enumeration e = pathComponents.elements(); e.hasMoreElements();) {
  1176. File pathComponent = (File) e.nextElement();
  1177. if (pathComponent.equals(component)) {
  1178. return true;
  1179. }
  1180. }
  1181. return false;
  1182. }
  1183. /**
  1184. * Finds a class on the given classpath.
  1185. *
  1186. * @param name The name of the class to be loaded. Must not be
  1187. * <code>null</code>.
  1188. *
  1189. * @return the required Class object
  1190. *
  1191. * @exception ClassNotFoundException if the requested class does not exist
  1192. * on this loader's classpath.
  1193. */
  1194. private Class findClassInComponents(String name)
  1195. throws ClassNotFoundException {
  1196. // we need to search the components of the path to see if
  1197. // we can find the class we want.
  1198. InputStream stream = null;
  1199. String classFilename = getClassFilename(name);
  1200. try {
  1201. Enumeration e = pathComponents.elements();
  1202. while (e.hasMoreElements()) {
  1203. File pathComponent = (File) e.nextElement();
  1204. try {
  1205. stream = getResourceStream(pathComponent, classFilename);
  1206. if (stream != null) {
  1207. log("Loaded from " + pathComponent + " "
  1208. + classFilename, Project.MSG_DEBUG);
  1209. return getClassFromStream(stream, name, pathComponent);
  1210. }
  1211. } catch (SecurityException se) {
  1212. throw se;
  1213. } catch (IOException ioe) {
  1214. // ioe.printStackTrace();
  1215. log("Exception reading component " + pathComponent
  1216. + " (reason: " + ioe.getMessage() + ")",
  1217. Project.MSG_VERBOSE);
  1218. }
  1219. }
  1220. throw new ClassNotFoundException(name);
  1221. } finally {
  1222. try {
  1223. if (stream != null) {
  1224. stream.close();
  1225. }
  1226. } catch (IOException e) {
  1227. //ignore
  1228. }
  1229. }
  1230. }
  1231. /**
  1232. * Finds a system class (which should be loaded from the same classloader
  1233. * as the Ant core).
  1234. *
  1235. * For JDK 1.1 compatibility, this uses the findSystemClass method if
  1236. * no parent classloader has been specified.
  1237. *
  1238. * @param name The name of the class to be loaded.
  1239. * Must not be <code>null</code>.
  1240. *
  1241. * @return the required Class object
  1242. *
  1243. * @exception ClassNotFoundException if the requested class does not exist
  1244. * on this loader's classpath.
  1245. */
  1246. private Class findBaseClass(String name) throws ClassNotFoundException {
  1247. if (parent == null) {
  1248. return findSystemClass(name);
  1249. } else {
  1250. return parent.loadClass(name);
  1251. }
  1252. }
  1253. /**
  1254. * Cleans up any resources held by this classloader. Any open archive
  1255. * files are closed.
  1256. */
  1257. public synchronized void cleanup() {
  1258. for (Enumeration e = zipFiles.elements(); e.hasMoreElements();) {
  1259. ZipFile zipFile = (ZipFile) e.nextElement();
  1260. try {
  1261. zipFile.close();
  1262. } catch (IOException ioe) {
  1263. // ignore
  1264. }
  1265. }
  1266. zipFiles = new Hashtable();
  1267. if (project != null) {
  1268. project.removeBuildListener(this);
  1269. }
  1270. project = null;
  1271. }
  1272. /**
  1273. * Empty implementation to satisfy the BuildListener interface.
  1274. *
  1275. * @param event the buildStarted event
  1276. */
  1277. public void buildStarted(BuildEvent event) {
  1278. // Not significant for the class loader.
  1279. }
  1280. /**
  1281. * Cleans up any resources held by this classloader at the end
  1282. * of a build.
  1283. *
  1284. * @param event the buildFinished event
  1285. */
  1286. public void buildFinished(BuildEvent event) {
  1287. cleanup();
  1288. }
  1289. /**
  1290. * Cleans up any resources held by this classloader at the end of
  1291. * a subbuild if it has been created for the subbuild's project
  1292. * instance.
  1293. *
  1294. * @param event the buildFinished event
  1295. *
  1296. * @since Ant 1.6.2
  1297. */
  1298. public void subBuildFinished(BuildEvent event) {
  1299. if (event.getProject() == project) {
  1300. cleanup();
  1301. }
  1302. }
  1303. /**
  1304. * Empty implementation to satisfy the BuildListener interface.
  1305. *
  1306. * @param event the buildStarted event
  1307. *
  1308. * @since Ant 1.6.2
  1309. */
  1310. public void subBuildStarted(BuildEvent event) {
  1311. // Not significant for the class loader.
  1312. }
  1313. /**
  1314. * Empty implementation to satisfy the BuildListener interface.
  1315. *
  1316. * @param event the targetStarted event
  1317. */
  1318. public void targetStarted(BuildEvent event) {
  1319. // Not significant for the class loader.
  1320. }
  1321. /**
  1322. * Empty implementation to satisfy the BuildListener interface.
  1323. *
  1324. * @param event the targetFinished event
  1325. */
  1326. public void targetFinished(BuildEvent event) {
  1327. // Not significant for the class loader.
  1328. }
  1329. /**
  1330. * Empty implementation to satisfy the BuildListener interface.
  1331. *
  1332. * @param event the taskStarted event
  1333. */
  1334. public void taskStarted(BuildEvent event) {
  1335. // Not significant for the class loader.
  1336. }
  1337. /**
  1338. * Empty implementation to satisfy the BuildListener interface.
  1339. *
  1340. * @param event the taskFinished event
  1341. */
  1342. public void taskFinished(BuildEvent event) {
  1343. // Not significant for the class loader.
  1344. }
  1345. /**
  1346. * Empty implementation to satisfy the BuildListener interface.
  1347. *
  1348. * @param event the messageLogged event
  1349. */
  1350. public void messageLogged(BuildEvent event) {
  1351. // Not significant for the class loader.
  1352. }
  1353. /**
  1354. * add any libraries that come with different java versions
  1355. * here
  1356. */
  1357. public void addJavaLibraries() {
  1358. Vector packages = JavaEnvUtils.getJrePackages();
  1359. Enumeration e = packages.elements();
  1360. while (e.hasMoreElements()) {
  1361. String packageName = (String) e.nextElement();
  1362. addSystemPackageRoot(packageName);
  1363. }
  1364. }
  1365. }