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 62 kB

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