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.

TaskManager.java 9.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // -------------------------------------------------------------------------------
  2. // Copyright (c)2000 Apache Software Foundation
  3. // -------------------------------------------------------------------------------
  4. package org.apache.ant;
  5. import java.io.*;
  6. import java.net.*;
  7. import java.util.*;
  8. import java.util.zip.*;
  9. /**
  10. * Manager of tasks and all things related to tasks. Tasks can be found in a
  11. * wide number of locations -- and most of these locations require class loading
  12. * help. As well, new nodes on the task search path may be added at any time.
  13. * When these are added, new tasks should be scanned for.
  14. *
  15. * @author James Duncan Davidson (duncan@apache.org)
  16. */
  17. public class TaskManager {
  18. // -----------------------------------------------------------------
  19. // PRIVATE DATA MEMBERS
  20. // -----------------------------------------------------------------
  21. /**
  22. * FrontEnd that this TaskManager can communicate through.
  23. */
  24. private FrontEnd frontEnd;
  25. /**
  26. * Data structure where all the Class definition for all known tasks are
  27. * held.
  28. */
  29. private Hashtable taskClasses = new Hashtable();
  30. /**
  31. * Data structure that holds all the nodes where tasks are picked up from.
  32. */
  33. private Vector taskPathNodes = new Vector();
  34. // -----------------------------------------------------------------
  35. // CONSTRUCTORS
  36. // -----------------------------------------------------------------
  37. /**
  38. * Creates a new TaskManager.
  39. */
  40. TaskManager(FrontEnd frontEnd) {
  41. this.frontEnd = frontEnd;
  42. }
  43. // -----------------------------------------------------------------
  44. // PUBLIC METHODS
  45. // -----------------------------------------------------------------
  46. /**
  47. * Adds a node to the task path
  48. */
  49. public void addTaskPathNode(File file) throws AntException {
  50. taskPathNodes.addElement(file);
  51. processTaskPathNode(file);
  52. }
  53. // -----------------------------------------------------------------
  54. // PACKAGE METHODS
  55. // -----------------------------------------------------------------
  56. /**
  57. *
  58. */
  59. AbstractTask getTaskInstance(String taskName) throws AntException {
  60. Class clazz = (Class)taskClasses.get(taskName);
  61. try {
  62. return (AbstractTask)clazz.newInstance();
  63. } catch (Exception e) {
  64. String msg = "Can't instantiate task: " + taskName;
  65. AntException ae = new AntException(msg, e);
  66. throw ae;
  67. }
  68. }
  69. // -----------------------------------------------------------------
  70. // PRIVATE METHODS
  71. // -----------------------------------------------------------------
  72. /**
  73. * Returns an enum of the task names that are defined in a given
  74. * properties file.
  75. */
  76. private Enumeration getTaskNames(Properties props) {
  77. Vector v = new Vector();
  78. String s = props.getProperty("tasks");
  79. StringTokenizer tok = new StringTokenizer(s, ",", false);
  80. while (tok.hasMoreTokens()) {
  81. String taskName = tok.nextToken().trim();
  82. v.addElement(taskName);
  83. }
  84. return v.elements();
  85. }
  86. /**
  87. * Processes a directory to get class defintions from it
  88. */
  89. private void processDir(File dir) {
  90. frontEnd.writeMessage("Scanning " + dir + " for tasks",
  91. FrontEnd.MSG_LEVEL_LOW);
  92. File file = new File(dir, "taskdef.properties");
  93. if (file.exists()) {
  94. try {
  95. InputStream in = new FileInputStream(file);
  96. Properties props = new Properties();
  97. props.load(in);
  98. in.close();
  99. Enumeration enum = getTaskNames(props);
  100. while (enum.hasMoreElements()) {
  101. String taskName = (String)enum.nextElement();
  102. String taskClass = props.getProperty("task." + taskName + ".class");
  103. URLClassLoader loader = new URLClassLoader(new URL[] {dir.toURL()});
  104. try {
  105. Class clazz = loader.loadClass(taskClass);
  106. frontEnd.writeMessage("Got Task: " + taskName +
  107. clazz, FrontEnd.MSG_LEVEL_LOW);
  108. taskClasses.put(taskName, clazz);
  109. } catch (ClassNotFoundException cnfe) {
  110. System.out.println("Couldn't load task: " + taskName);
  111. System.out.println(cnfe);
  112. // XXX error out and stop....
  113. }
  114. }
  115. } catch (IOException ioe) {
  116. System.out.println("Could not work with dir: " + dir);
  117. System.out.println(ioe);
  118. // XXX error out and stop the build
  119. }
  120. }
  121. }
  122. /**
  123. * Processes a jar file to get class definitions from it
  124. */
  125. private void processJar(File file) throws AntException {
  126. frontEnd.writeMessage("Scanning " + file + " for tasks",
  127. FrontEnd.MSG_LEVEL_LOW);
  128. try {
  129. ZipFile zipFile = new ZipFile(file);
  130. ZipEntry zipEntry = zipFile.getEntry("taskdef.properties");
  131. if (zipEntry != null) {
  132. InputStream in = zipFile.getInputStream(zipEntry);
  133. Properties props = new Properties();
  134. props.load(in);
  135. in.close();
  136. Enumeration enum = getTaskNames(props);
  137. while (enum.hasMoreElements()) {
  138. String taskName = (String)enum.nextElement();
  139. String taskClass = props.getProperty("task." + taskName + ".class");
  140. if (taskClass == null) {
  141. String msg = "No class definition for task " + taskName +
  142. "in jar file " + file;
  143. throw new AntException(msg);
  144. }
  145. URLClassLoader loader = new URLClassLoader(new URL[] {file.toURL()});
  146. try {
  147. Class clazz = loader.loadClass(taskClass);
  148. frontEnd.writeMessage("Got Task: " + taskName +
  149. clazz, FrontEnd.MSG_LEVEL_LOW);
  150. taskClasses.put(taskName, clazz);
  151. } catch (ClassNotFoundException cnfe) {
  152. System.out.println("Couldn't load task: " + taskName);
  153. System.out.println(cnfe);
  154. // XXX error out and stop....
  155. }
  156. }
  157. }
  158. // make sure to not leave resources hanging
  159. zipFile.close();
  160. } catch (IOException ioe) {
  161. System.out.println("Couldn't work with file: " + file);
  162. System.out.println(ioe);
  163. // XXX need to exception out of here properly to stop things
  164. }
  165. }
  166. /**
  167. * Processes a node of the task path searching for task definitions there
  168. * and adding them to the list of known tasks
  169. */
  170. private void processTaskPathNode(File file) throws AntException {
  171. // task path nodes can be any of the following:
  172. // * jar file
  173. // * directory of jar files
  174. // * directory holding class files
  175. if(file.isDirectory()) {
  176. // first look for all jar files here
  177. // second look for a taskdefs.properties here to see if we should
  178. // treat the directory as a classpath
  179. String[] files = file.list();
  180. for (int i = 0; i < files.length; i++) {
  181. if (files[i].endsWith(".jar")) {
  182. processJar(new File(file, files[i]));
  183. } else if (files[i].equals("taskdef.properties")) {
  184. processDir(file);
  185. }
  186. }
  187. } else if (file.getName().endsWith(".jar")) {
  188. processJar(file);
  189. }
  190. }
  191. /**
  192. * Sets up the taskpath based on the currently running operating
  193. * system. In general, the ordering of the taskpath is: user directory,
  194. * system directory, and then installation. This allows users or
  195. * system admins to override or add tasks.
  196. */
  197. private void setUpTaskPath() throws AntException {
  198. // 1st, add user's home dir.
  199. File f;
  200. String userHome = System.getProperty("user.home");
  201. // generic unix
  202. f = new File(userHome + ".ant", "tasks");
  203. if (f.exists() && f.isDirectory()) {
  204. addTaskPathNode(f);
  205. }
  206. // macos x
  207. f = new File(userHome + "/Library/Ant", "Tasks");
  208. if (f.exists() && f.isDirectory()) {
  209. addTaskPathNode(f);
  210. }
  211. // windows -- todo
  212. // 2nd, add system local dir.
  213. // generic unix
  214. f = new File("/usr/local/ant/tasks");
  215. if (f.exists() && f.isDirectory()) {
  216. addTaskPathNode(f);
  217. }
  218. // macos x
  219. f = new File("/Library/Ant/Tasks");
  220. if (f.exists() && f.isDirectory()) {
  221. addTaskPathNode(f);
  222. }
  223. // windows -- todo
  224. // 3rd, add installation local dir.
  225. //System.out.println("BASE: " + this.getClass().getResource("/"));
  226. // XXX ---- not really sure how the best way of getting this info is...
  227. // hafta think about it.
  228. }
  229. }