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.

Classloader.java 8.2 kB

11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. * http://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.taskdefs;
  19. import java.io.File;
  20. import org.apache.tools.ant.AntClassLoader;
  21. import org.apache.tools.ant.BuildException;
  22. import org.apache.tools.ant.MagicNames;
  23. import org.apache.tools.ant.Project;
  24. import org.apache.tools.ant.Task;
  25. import org.apache.tools.ant.types.Path;
  26. import org.apache.tools.ant.types.Reference;
  27. import org.apache.tools.ant.util.StringUtils;
  28. /**
  29. * EXPERIMENTAL
  30. * Create or modifies ClassLoader. The required pathRef parameter
  31. * will be used to add classpath elements.
  32. *
  33. * The classpath is a regular path. Currently only file components are
  34. * supported (future extensions may allow URLs).
  35. *
  36. * You can modify the core loader by not specifying any name or using
  37. * "ant.coreLoader". (the core loader is used to load system ant
  38. * tasks and for taskdefs that don't specify an explicit path).
  39. *
  40. * Taskdef and typedef can use the loader you create if the name follows
  41. * the "ant.loader.NAME" pattern. NAME will be used as a pathref when
  42. * calling taskdef.
  43. *
  44. * This tasks will not modify the core loader if "build.sysclasspath=only"
  45. *
  46. * The typical use is:
  47. * <pre>
  48. * &lt;path id="ant.deps" &gt;
  49. * &lt;fileset dir="myDir" &gt;
  50. * &lt;include name="junit.jar, bsf.jar, js.jar, etc"/&gt;
  51. * &lt;/fileset&gt;
  52. * &lt;/path&gt;
  53. *
  54. * &lt;classloader pathRef="ant.deps" /&gt;
  55. *
  56. * </pre>
  57. *
  58. */
  59. public class Classloader extends Task {
  60. /** @see MagicNames#SYSTEM_LOADER_REF */
  61. public static final String SYSTEM_LOADER_REF = MagicNames.SYSTEM_LOADER_REF;
  62. private String name = null;
  63. private Path classpath;
  64. private boolean reset = false;
  65. private boolean parentFirst = true;
  66. private String parentName = null;
  67. /**
  68. * Default constructor
  69. */
  70. public Classloader() {
  71. }
  72. /** Name of the loader. If none, the default loader will be modified
  73. *
  74. * @param name the name of this loader
  75. */
  76. public void setName(String name) {
  77. this.name = name;
  78. }
  79. /**
  80. * Reset the classloader, if it already exists. A new loader will
  81. * be created and all the references to the old one will be removed.
  82. * (it is not possible to remove paths from a loader). The new
  83. * path will be used.
  84. *
  85. * @param b true if the loader is to be reset.
  86. */
  87. public void setReset(boolean b) {
  88. this.reset = b;
  89. }
  90. /**
  91. * Set reverse attribute.
  92. * @param b if true reverse the normal classloader lookup.
  93. * @deprecated use setParentFirst with a negated argument instead
  94. */
  95. public void setReverse(boolean b) {
  96. this.parentFirst = !b;
  97. }
  98. /**
  99. * Set reverse attribute.
  100. * @param b if true reverse the normal classloader lookup.
  101. */
  102. public void setParentFirst(boolean b) {
  103. this.parentFirst = b;
  104. }
  105. /**
  106. * Set the name of the parent.
  107. * @param name the parent name.
  108. */
  109. public void setParentName(String name) {
  110. this.parentName = name;
  111. }
  112. /** Specify which path will be used. If the loader already exists
  113. * and is an AntClassLoader (or any other loader we can extend),
  114. * the path will be added to the loader.
  115. * @param pathRef a reference to a path.
  116. * @throws BuildException if there is a problem.
  117. */
  118. public void setClasspathRef(Reference pathRef) throws BuildException {
  119. classpath = (Path) pathRef.getReferencedObject(getProject());
  120. }
  121. /**
  122. * Set the classpath to be used when searching for component being defined
  123. *
  124. * @param classpath an Ant Path object containing the classpath.
  125. */
  126. public void setClasspath(Path classpath) {
  127. if (this.classpath == null) {
  128. this.classpath = classpath;
  129. } else {
  130. this.classpath.append(classpath);
  131. }
  132. }
  133. /**
  134. * Create a classpath.
  135. * @return a path for configuration.
  136. */
  137. public Path createClasspath() {
  138. if (this.classpath == null) {
  139. this.classpath = new Path(null);
  140. }
  141. return this.classpath.createPath();
  142. }
  143. /**
  144. * do the classloader manipulation.
  145. */
  146. public void execute() {
  147. try {
  148. // Gump friendly - don't mess with the core loader if only classpath
  149. if ("only".equals(getProject().getProperty("build.sysclasspath"))
  150. && (name == null || SYSTEM_LOADER_REF.equals(name))) {
  151. log("Changing the system loader is disabled "
  152. + "by build.sysclasspath=only", Project.MSG_WARN);
  153. return;
  154. }
  155. String loaderName = (name == null) ? SYSTEM_LOADER_REF : name;
  156. Object obj = getProject().getReference(loaderName);
  157. if (reset) {
  158. // Are any other references held ? Can we 'close' the loader
  159. // so it removes the locks on jars ?
  160. obj = null; // a new one will be created.
  161. }
  162. // TODO maybe use reflection to addPathElement (other patterns ?)
  163. if (obj != null && !(obj instanceof AntClassLoader)) {
  164. log("Referenced object is not an AntClassLoader",
  165. Project.MSG_ERR);
  166. return;
  167. }
  168. AntClassLoader acl = (AntClassLoader) obj;
  169. boolean existingLoader = acl != null;
  170. if (acl == null) {
  171. // Construct a new class loader
  172. Object parent = null;
  173. if (parentName != null) {
  174. parent = getProject().getReference(parentName);
  175. if (!(parent instanceof ClassLoader)) {
  176. parent = null;
  177. }
  178. }
  179. // TODO: allow user to request the system or no parent
  180. if (parent == null) {
  181. parent = this.getClass().getClassLoader();
  182. }
  183. if (name == null) {
  184. // The core loader must be reverse
  185. //reverse=true;
  186. }
  187. getProject().log("Setting parent loader " + name + " "
  188. + parent + " " + parentFirst, Project.MSG_DEBUG);
  189. // The param is "parentFirst"
  190. acl = AntClassLoader.newAntClassLoader((ClassLoader) parent,
  191. getProject(), classpath, parentFirst);
  192. getProject().addReference(loaderName, acl);
  193. if (name == null) {
  194. // This allows the core loader to load optional tasks
  195. // without delegating
  196. acl.addLoaderPackageRoot("org.apache.tools.ant.taskdefs.optional");
  197. getProject().setCoreLoader(acl);
  198. }
  199. }
  200. if (existingLoader && classpath != null) {
  201. String[] list = classpath.list();
  202. for (int i = 0; i < list.length; i++) {
  203. File f = new File(list[i]);
  204. if (f.exists()) {
  205. log("Adding to class loader " + acl + " " + f.getAbsolutePath(),
  206. Project.MSG_DEBUG);
  207. acl.addPathElement(f.getAbsolutePath());
  208. }
  209. }
  210. }
  211. // TODO add exceptions
  212. } catch (Exception ex) {
  213. log(StringUtils.getStackTrace(ex), Project.MSG_ERR);
  214. }
  215. }
  216. }