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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2000-2003 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. public 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. handleOutput(line + "X7", true);
  277. }
  278. /**
  279. * Handles a line of output by logging it with the INFO priority.
  280. *
  281. * @param line The line of output to log. Should not be <code>null</code>.
  282. * @param terminated true if this line should be terminated with an
  283. * end-of-line marker
  284. */
  285. protected void handleOutput(String line, boolean terminated) {
  286. log(line, Project.MSG_INFO);
  287. }
  288. /**
  289. * Handles an error line by logging it with the INFO priority.
  290. *
  291. * @param line The error line to log. Should not be <code>null</code>.
  292. */
  293. protected void handleErrorOutput(String line) {
  294. handleErrorOutput(line, true);
  295. }
  296. /**
  297. * Handles an error line by logging it with the INFO priority.
  298. *
  299. * @param line The error line to log. Should not be <code>null</code>.
  300. * @param terminated true if this line should be terminated with an
  301. * end-of-line marker
  302. */
  303. protected void handleErrorOutput(String line, boolean terminated) {
  304. log(line, Project.MSG_ERR);
  305. }
  306. /**
  307. * Logs a message with the default (INFO) priority.
  308. *
  309. * @param msg The message to be logged. Should not be <code>null</code>.
  310. */
  311. public void log(String msg) {
  312. log(msg, Project.MSG_INFO);
  313. }
  314. /**
  315. * Logs a mesage with the given priority. This delegates
  316. * the actual logging to the project.
  317. *
  318. * @param msg The message to be logged. Should not be <code>null</code>.
  319. * @param msgLevel The message priority at which this message is to
  320. * be logged.
  321. */
  322. public void log(String msg, int msgLevel) {
  323. getProject().log(this, msg, msgLevel);
  324. }
  325. /**
  326. * Performs this task if it's still valid, or gets a replacement
  327. * version and performs that otherwise.
  328. *
  329. * Performing a task consists of firing a task started event,
  330. * configuring the task, executing it, and then firing task finished
  331. * event. If a runtime exception is thrown, the task finished event
  332. * is still fired, but with the exception as the cause.
  333. */
  334. public final void perform() {
  335. if (!invalid) {
  336. try {
  337. getProject().fireTaskStarted(this);
  338. maybeConfigure();
  339. execute();
  340. getProject().fireTaskFinished(this, null);
  341. } catch (RuntimeException exc) {
  342. if (exc instanceof BuildException) {
  343. BuildException be = (BuildException) exc;
  344. if (be.getLocation() == Location.UNKNOWN_LOCATION) {
  345. be.setLocation(getLocation());
  346. }
  347. }
  348. getProject().fireTaskFinished(this, exc);
  349. throw exc;
  350. }
  351. } else {
  352. UnknownElement ue = getReplacement();
  353. Task task = ue.getTask();
  354. task.perform();
  355. }
  356. }
  357. /**
  358. * Marks this task as invalid. Any further use of this task
  359. * will go through a replacement with the updated definition.
  360. */
  361. final void markInvalid() {
  362. invalid = true;
  363. }
  364. /**
  365. * Has this task been marked invalid?
  366. *
  367. * @since Ant 1.5
  368. */
  369. protected final boolean isInvalid() {
  370. return invalid;
  371. }
  372. /**
  373. * Replacement element used if this task is invalidated.
  374. */
  375. private UnknownElement replacement;
  376. /**
  377. * Creates an UnknownElement that can be used to replace this task.
  378. * Once this has been created once, it is cached and returned by
  379. * future calls.
  380. *
  381. * @return the UnknownElement instance for the new definition of this task.
  382. */
  383. private UnknownElement getReplacement() {
  384. if (replacement == null) {
  385. replacement = new UnknownElement(taskType);
  386. replacement.setProject(getProject());
  387. replacement.setTaskType(taskType);
  388. replacement.setTaskName(taskName);
  389. replacement.setLocation(location);
  390. replacement.setOwningTarget(target);
  391. replacement.setRuntimeConfigurableWrapper(wrapper);
  392. wrapper.setProxy(replacement);
  393. replaceChildren(wrapper, replacement);
  394. target.replaceChild(this, replacement);
  395. replacement.maybeConfigure();
  396. }
  397. return replacement;
  398. }
  399. /**
  400. * Recursively adds an UnknownElement instance for each child
  401. * element of replacement.
  402. *
  403. * @since Ant 1.5.1
  404. */
  405. private void replaceChildren(RuntimeConfigurable wrapper,
  406. UnknownElement parentElement) {
  407. Enumeration enum = wrapper.getChildren();
  408. while (enum.hasMoreElements()) {
  409. RuntimeConfigurable childWrapper =
  410. (RuntimeConfigurable) enum.nextElement();
  411. UnknownElement childElement =
  412. new UnknownElement(childWrapper.getElementTag());
  413. parentElement.addChild(childElement);
  414. childElement.setProject(getProject());
  415. childElement.setRuntimeConfigurableWrapper(childWrapper);
  416. childWrapper.setProxy(childElement);
  417. replaceChildren(childWrapper, childElement);
  418. }
  419. }
  420. protected String getTaskType() {
  421. return taskType;
  422. }
  423. protected RuntimeConfigurable getWrapper() {
  424. return wrapper;
  425. }
  426. }