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.

Task.java 15 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowlegement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowlegement may appear in the software itself,
  24. * if and wherever such third-party acknowlegements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Ant", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Group.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.tools.ant;
  55. import java.util.Enumeration;
  56. /**
  57. * Base class for all tasks.
  58. *
  59. * Use Project.createTask to create a new task instance rather than
  60. * using this class directly for construction.
  61. *
  62. * @see Project#createTask
  63. */
  64. public abstract class Task extends ProjectComponent {
  65. /**
  66. * Target this task belongs to, if any.
  67. * @deprecated You should not be accessing this variable directly.
  68. * Please use the {@link #getOwningTarget()} method.
  69. */
  70. protected Target target;
  71. /**
  72. * Description of this task, if any.
  73. * @deprecated You should not be accessing this variable directly.
  74. */
  75. protected String description;
  76. /**
  77. * Location within the build file of this task definition.
  78. * @deprecated You should not be accessing this variable directly.
  79. * Please use the {@link #getLocation()} method.
  80. */
  81. protected Location location = Location.UNKNOWN_LOCATION;
  82. /**
  83. * Name of this task to be used for logging purposes.
  84. * This defaults to the same as the type, but may be
  85. * overridden by the user. For instance, the name "java"
  86. * isn't terribly descriptive for a task used within
  87. * another task - the outer task code can probably
  88. * provide a better one.
  89. * @deprecated You should not be accessing this variable directly.
  90. * Please use the {@link #getTaskName()} method.
  91. */
  92. protected String taskName;
  93. /**
  94. * Type of this task.
  95. *
  96. * @deprecated You should not be accessing this variable directly.
  97. * Please use the {@link #getTaskType()} method.
  98. */
  99. protected String taskType;
  100. /**
  101. * Wrapper for this object, used to configure it at runtime.
  102. *
  103. * @deprecated You should not be accessing this variable directly.
  104. * Please use the {@link #getWrapper()} method.
  105. */
  106. protected RuntimeConfigurable wrapper;
  107. /**
  108. * Whether or not this task is invalid. A task becomes invalid
  109. * if a conflicting class is specified as the implementation for
  110. * its type.
  111. */
  112. private boolean invalid;
  113. /** Sole constructor. */
  114. public Task() {
  115. }
  116. /**
  117. * Sets the target container of this task.
  118. *
  119. * @param target Target in whose scope this task belongs.
  120. * May be <code>null</code>, indicating a top-level task.
  121. */
  122. public void setOwningTarget(Target target) {
  123. this.target = target;
  124. }
  125. /**
  126. * Returns the container target of this task.
  127. *
  128. * @return The target containing this task, or <code>null</code> if
  129. * this task is a top-level task.
  130. */
  131. public Target getOwningTarget() {
  132. return target;
  133. }
  134. /**
  135. * Sets the name to use in logging messages.
  136. *
  137. * @param name The name to use in logging messages.
  138. * Should not be <code>null</code>.
  139. */
  140. public void setTaskName(String name) {
  141. this.taskName = name;
  142. }
  143. /**
  144. * Returns the name to use in logging messages.
  145. *
  146. * @return the name to use in logging messages.
  147. */
  148. public String getTaskName() {
  149. return taskName;
  150. }
  151. /**
  152. * Sets the name with which the task has been invoked.
  153. *
  154. * @param type The name the task has been invoked as.
  155. * Should not be <code>null</code>.
  156. */
  157. void setTaskType(String type) {
  158. this.taskType = type;
  159. }
  160. /**
  161. * Sets a description of the current action. This may be used for logging
  162. * purposes.
  163. *
  164. * @param desc Description of the current action.
  165. * May be <code>null</code>, indicating that no description is
  166. * available.
  167. *
  168. */
  169. public void setDescription(String desc) {
  170. description = desc;
  171. }
  172. /**
  173. * Returns the description of the current action.
  174. *
  175. * @return the description of the current action, or <code>null</code> if
  176. * no description is available.
  177. */
  178. public String getDescription() {
  179. return description;
  180. }
  181. /**
  182. * Called by the project to let the task initialize properly.
  183. * The default implementation is a no-op.
  184. *
  185. * @exception BuildException if someting goes wrong with the build
  186. */
  187. public void init() throws BuildException {}
  188. /**
  189. * Called by the project to let the task do its work. This method may be
  190. * called more than once, if the task is invoked more than once.
  191. * For example,
  192. * if target1 and target2 both depend on target3, then running
  193. * "ant target1 target2" will run all tasks in target3 twice.
  194. *
  195. * @exception BuildException if something goes wrong with the build
  196. */
  197. public void execute() throws BuildException {}
  198. /**
  199. * Returns the file/location where this task was defined.
  200. *
  201. * @return the file/location where this task was defined.
  202. * Should not return <code>null</code>. Location.UNKNOWN_LOCATION
  203. * is used for unknown locations.
  204. *
  205. * @see Location#UNKNOWN_LOCATION
  206. */
  207. public Location getLocation() {
  208. return location;
  209. }
  210. /**
  211. * Sets the file/location where this task was defined.
  212. *
  213. * @param location The file/location where this task was defined.
  214. * Should not be <code>null</code> - use
  215. * Location.UNKNOWN_LOCATION if the location isn't known.
  216. *
  217. * @see Location#UNKNOWN_LOCATION
  218. */
  219. public void setLocation(Location location) {
  220. this.location = location;
  221. }
  222. /**
  223. * Returns the wrapper used for runtime configuration.
  224. *
  225. * @return the wrapper used for runtime configuration. This
  226. * method will generate a new wrapper (and cache it)
  227. * if one isn't set already.
  228. */
  229. public RuntimeConfigurable getRuntimeConfigurableWrapper() {
  230. if (wrapper == null) {
  231. wrapper = new RuntimeConfigurable(this, getTaskName());
  232. }
  233. return wrapper;
  234. }
  235. /**
  236. * Sets the wrapper to be used for runtime configuration.
  237. *
  238. * This method should be used only by the ProjectHelper and ant internals.
  239. * It is public to allow helper plugins to operate on tasks, normal tasks
  240. * should never use it.
  241. *
  242. * @param wrapper The wrapper to be used for runtime configuration.
  243. * May be <code>null</code>, in which case the next call
  244. * to getRuntimeConfigurableWrapper will generate a new
  245. * wrapper.
  246. */
  247. public void setRuntimeConfigurableWrapper(RuntimeConfigurable wrapper) {
  248. this.wrapper = wrapper;
  249. }
  250. // XXX: (Jon Skeet) The comment "if it hasn't been done already" may
  251. // not be strictly true. wrapper.maybeConfigure() won't configure the same
  252. // attributes/text more than once, but it may well add the children again,
  253. // unless I've missed something.
  254. /**
  255. * Configures this task - if it hasn't been done already.
  256. * If the task has been invalidated, it is replaced with an
  257. * UnknownElement task which uses the new definition in the project.
  258. *
  259. * @exception BuildException if the task cannot be configured.
  260. */
  261. public void maybeConfigure() throws BuildException {
  262. if (!invalid) {
  263. if (wrapper != null) {
  264. wrapper.maybeConfigure(getProject());
  265. }
  266. } else {
  267. getReplacement();
  268. }
  269. }
  270. /**
  271. * Handles a line of output by logging it with the INFO priority.
  272. *
  273. * @param line The line of output to log. Should not be <code>null</code>.
  274. */
  275. protected void handleOutput(String line) {
  276. log(line, Project.MSG_INFO);
  277. }
  278. /**
  279. * Handles an error line by logging it with the INFO priority.
  280. *
  281. * @param line The error line to log. Should not be <code>null</code>.
  282. */
  283. protected void handleErrorOutput(String line) {
  284. log(line, Project.MSG_ERR);
  285. }
  286. /**
  287. * Logs a message with the default (INFO) priority.
  288. *
  289. * @param msg The message to be logged. Should not be <code>null</code>.
  290. */
  291. public void log(String msg) {
  292. log(msg, Project.MSG_INFO);
  293. }
  294. /**
  295. * Logs a mesage with the given priority. This delegates
  296. * the actual logging to the project.
  297. *
  298. * @param msg The message to be logged. Should not be <code>null</code>.
  299. * @param msgLevel The message priority at which this message is to
  300. * be logged.
  301. */
  302. public void log(String msg, int msgLevel) {
  303. getProject().log(this, msg, msgLevel);
  304. }
  305. /**
  306. * Performs this task if it's still valid, or gets a replacement
  307. * version and performs that otherwise.
  308. *
  309. * Performing a task consists of firing a task started event,
  310. * configuring the task, executing it, and then firing task finished
  311. * event. If a runtime exception is thrown, the task finished event
  312. * is still fired, but with the exception as the cause.
  313. */
  314. public final void perform() {
  315. if (!invalid) {
  316. try {
  317. getProject().fireTaskStarted(this);
  318. maybeConfigure();
  319. execute();
  320. getProject().fireTaskFinished(this, null);
  321. } catch (RuntimeException exc) {
  322. if (exc instanceof BuildException) {
  323. BuildException be = (BuildException) exc;
  324. if (be.getLocation() == Location.UNKNOWN_LOCATION) {
  325. be.setLocation(getLocation());
  326. }
  327. }
  328. getProject().fireTaskFinished(this, exc);
  329. throw exc;
  330. }
  331. } else {
  332. UnknownElement ue = getReplacement();
  333. Task task = ue.getTask();
  334. task.perform();
  335. }
  336. }
  337. /**
  338. * Marks this task as invalid. Any further use of this task
  339. * will go through a replacement with the updated definition.
  340. */
  341. final void markInvalid() {
  342. invalid = true;
  343. }
  344. /**
  345. * Has this task been marked invalid?
  346. *
  347. * @since Ant 1.5
  348. */
  349. protected final boolean isInvalid() {
  350. return invalid;
  351. }
  352. /**
  353. * Replacement element used if this task is invalidated.
  354. */
  355. private UnknownElement replacement;
  356. /**
  357. * Creates an UnknownElement that can be used to replace this task.
  358. * Once this has been created once, it is cached and returned by
  359. * future calls.
  360. *
  361. * @return the UnknownElement instance for the new definition of this task.
  362. */
  363. private UnknownElement getReplacement() {
  364. if (replacement == null) {
  365. replacement = new UnknownElement(taskType);
  366. replacement.setProject(getProject());
  367. replacement.setTaskType(taskType);
  368. replacement.setTaskName(taskName);
  369. replacement.setLocation(location);
  370. replacement.setOwningTarget(target);
  371. replacement.setRuntimeConfigurableWrapper(wrapper);
  372. wrapper.setProxy(replacement);
  373. replaceChildren(wrapper, replacement);
  374. target.replaceChild(this, replacement);
  375. replacement.maybeConfigure();
  376. }
  377. return replacement;
  378. }
  379. /**
  380. * Recursively adds an UnknownElement instance for each child
  381. * element of replacement.
  382. *
  383. * @since Ant 1.5.1
  384. */
  385. private void replaceChildren(RuntimeConfigurable wrapper,
  386. UnknownElement parentElement) {
  387. Enumeration enum = wrapper.getChildren();
  388. while (enum.hasMoreElements()) {
  389. RuntimeConfigurable childWrapper =
  390. (RuntimeConfigurable) enum.nextElement();
  391. UnknownElement childElement =
  392. new UnknownElement(childWrapper.getElementTag());
  393. parentElement.addChild(childElement);
  394. childElement.setRuntimeConfigurableWrapper(childWrapper);
  395. childWrapper.setProxy(childElement);
  396. replaceChildren(childWrapper, childElement);
  397. }
  398. }
  399. protected String getTaskType() {
  400. return taskType;
  401. }
  402. protected RuntimeConfigurable getWrapper() {
  403. return wrapper;
  404. }
  405. }