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

11 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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;
  19. import java.io.IOException;
  20. import java.util.Enumeration;
  21. import org.apache.tools.ant.dispatch.DispatchUtils;
  22. /**
  23. * Base class for all tasks.
  24. *
  25. * Use Project.createTask to create a new task instance rather than
  26. * using this class directly for construction.
  27. *
  28. * @see Project#createTask
  29. */
  30. public abstract class Task extends ProjectComponent {
  31. // CheckStyle:VisibilityModifier OFF - bc
  32. /**
  33. * Target this task belongs to, if any.
  34. * @deprecated since 1.6.x.
  35. * You should not be accessing this variable directly.
  36. * Please use the {@link #getOwningTarget()} method.
  37. */
  38. protected Target target;
  39. /**
  40. * Name of this task to be used for logging purposes.
  41. * This defaults to the same as the type, but may be
  42. * overridden by the user. For instance, the name "java"
  43. * isn't terribly descriptive for a task used within
  44. * another task - the outer task code can probably
  45. * provide a better one.
  46. * @deprecated since 1.6.x.
  47. * You should not be accessing this variable directly.
  48. * Please use the {@link #getTaskName()} method.
  49. */
  50. protected String taskName;
  51. /**
  52. * Type of this task.
  53. *
  54. * @deprecated since 1.6.x.
  55. * You should not be accessing this variable directly.
  56. * Please use the {@link #getTaskType()} method.
  57. */
  58. protected String taskType;
  59. /**
  60. * Wrapper for this object, used to configure it at runtime.
  61. *
  62. * @deprecated since 1.6.x.
  63. * You should not be accessing this variable directly.
  64. * Please use the {@link #getWrapper()} method.
  65. */
  66. protected RuntimeConfigurable wrapper;
  67. // CheckStyle:VisibilityModifier ON
  68. /**
  69. * Whether or not this task is invalid. A task becomes invalid
  70. * if a conflicting class is specified as the implementation for
  71. * its type.
  72. */
  73. private boolean invalid;
  74. /**
  75. * Sets the target container of this task.
  76. *
  77. * @param target Target in whose scope this task belongs.
  78. * May be <code>null</code>, indicating a top-level task.
  79. */
  80. public void setOwningTarget(Target target) {
  81. this.target = target;
  82. }
  83. /**
  84. * Returns the container target of this task.
  85. *
  86. * @return The target containing this task, or <code>null</code> if
  87. * this task is a top-level task.
  88. */
  89. public Target getOwningTarget() {
  90. return target;
  91. }
  92. /**
  93. * Sets the name to use in logging messages.
  94. *
  95. * @param name The name to use in logging messages.
  96. * Should not be <code>null</code>.
  97. */
  98. public void setTaskName(String name) {
  99. this.taskName = name;
  100. }
  101. /**
  102. * Returns the name to use in logging messages.
  103. *
  104. * @return the name to use in logging messages.
  105. */
  106. public String getTaskName() {
  107. return taskName;
  108. }
  109. /**
  110. * Sets the name with which the task has been invoked.
  111. *
  112. * @param type The name the task has been invoked as.
  113. * Should not be <code>null</code>.
  114. */
  115. public void setTaskType(String type) {
  116. this.taskType = type;
  117. }
  118. /**
  119. * Called by the project to let the task initialize properly.
  120. * The default implementation is a no-op.
  121. *
  122. * @exception BuildException if something goes wrong with the build
  123. */
  124. public void init() throws BuildException {
  125. }
  126. /**
  127. * Called by the project to let the task do its work. This method may be
  128. * called more than once, if the task is invoked more than once.
  129. * For example,
  130. * if target1 and target2 both depend on target3, then running
  131. * "ant target1 target2" will run all tasks in target3 twice.
  132. *
  133. * @exception BuildException if something goes wrong with the build.
  134. */
  135. public void execute() throws BuildException {
  136. }
  137. /**
  138. * Returns the wrapper used for runtime configuration.
  139. *
  140. * @return the wrapper used for runtime configuration. This
  141. * method will generate a new wrapper (and cache it)
  142. * if one isn't set already.
  143. */
  144. public RuntimeConfigurable getRuntimeConfigurableWrapper() {
  145. if (wrapper == null) {
  146. wrapper = new RuntimeConfigurable(this, getTaskName());
  147. }
  148. return wrapper;
  149. }
  150. /**
  151. * Sets the wrapper to be used for runtime configuration.
  152. *
  153. * This method should be used only by the ProjectHelper and Ant internals.
  154. * It is public to allow helper plugins to operate on tasks, normal tasks
  155. * should never use it.
  156. *
  157. * @param wrapper The wrapper to be used for runtime configuration.
  158. * May be <code>null</code>, in which case the next call
  159. * to getRuntimeConfigurableWrapper will generate a new
  160. * wrapper.
  161. */
  162. public void setRuntimeConfigurableWrapper(RuntimeConfigurable wrapper) {
  163. this.wrapper = wrapper;
  164. }
  165. // TODO: (Jon Skeet) The comment "if it hasn't been done already" may
  166. // not be strictly true. wrapper.maybeConfigure() won't configure the same
  167. // attributes/text more than once, but it may well add the children again,
  168. // unless I've missed something.
  169. /**
  170. * Configures this task - if it hasn't been done already.
  171. * If the task has been invalidated, it is replaced with an
  172. * UnknownElement task which uses the new definition in the project.
  173. *
  174. * @exception BuildException if the task cannot be configured.
  175. */
  176. public void maybeConfigure() throws BuildException {
  177. if (invalid) {
  178. getReplacement();
  179. } else if (wrapper != null) {
  180. wrapper.maybeConfigure(getProject());
  181. }
  182. }
  183. /**
  184. * Force the task to be reconfigured from its RuntimeConfigurable.
  185. */
  186. public void reconfigure() {
  187. if (wrapper != null) {
  188. wrapper.reconfigure(getProject());
  189. }
  190. }
  191. /**
  192. * Handles output by logging it with the INFO priority.
  193. *
  194. * @param output The output to log. Should not be <code>null</code>.
  195. */
  196. protected void handleOutput(String output) {
  197. log(output, Project.MSG_INFO);
  198. }
  199. /**
  200. * Handles output by logging it with the INFO priority.
  201. *
  202. * @param output The output to log. Should not be <code>null</code>.
  203. *
  204. * @since Ant 1.5.2
  205. */
  206. protected void handleFlush(String output) {
  207. handleOutput(output);
  208. }
  209. /**
  210. * Handle an input request by this task.
  211. *
  212. * @param buffer the buffer into which data is to be read.
  213. * @param offset the offset into the buffer at which data is stored.
  214. * @param length the amount of data to read.
  215. *
  216. * @return the number of bytes read.
  217. *
  218. * @exception IOException if the data cannot be read.
  219. * @since Ant 1.6
  220. */
  221. protected int handleInput(byte[] buffer, int offset, int length)
  222. throws IOException {
  223. return getProject().defaultInput(buffer, offset, length);
  224. }
  225. /**
  226. * Handles an error output by logging it with the WARN priority.
  227. *
  228. * @param output The error output to log. Should not be <code>null</code>.
  229. */
  230. protected void handleErrorOutput(String output) {
  231. log(output, Project.MSG_WARN);
  232. }
  233. /**
  234. * Handles an error line by logging it with the WARN priority.
  235. *
  236. * @param output The error output to log. Should not be <code>null</code>.
  237. *
  238. * @since Ant 1.5.2
  239. */
  240. protected void handleErrorFlush(String output) {
  241. handleErrorOutput(output);
  242. }
  243. /**
  244. * Logs a message with the default (INFO) priority.
  245. *
  246. * @param msg The message to be logged. Should not be <code>null</code>.
  247. */
  248. public void log(String msg) {
  249. log(msg, Project.MSG_INFO);
  250. }
  251. /**
  252. * Logs a message with the given priority. This delegates
  253. * the actual logging to the project.
  254. *
  255. * @param msg The message to be logged. Should not be <code>null</code>.
  256. * @param msgLevel The message priority at which this message is to
  257. * be logged.
  258. */
  259. public void log(String msg, int msgLevel) {
  260. if (getProject() == null) {
  261. super.log(msg, msgLevel);
  262. } else {
  263. getProject().log(this, msg, msgLevel);
  264. }
  265. }
  266. /**
  267. * Logs a message with the given priority. This delegates
  268. * the actual logging to the project.
  269. *
  270. * @param t The exception to be logged. Should not be <code>null</code>.
  271. * @param msgLevel The message priority at which this message is to
  272. * be logged.
  273. * @since 1.7
  274. */
  275. public void log(Throwable t, int msgLevel) {
  276. if (t != null) {
  277. log(t.getMessage(), t, msgLevel);
  278. }
  279. }
  280. /**
  281. * Logs a message with the given priority. This delegates
  282. * the actual logging to the project.
  283. *
  284. * @param msg The message to be logged. Should not be <code>null</code>.
  285. * @param t The exception to be logged. May be <code>null</code>.
  286. * @param msgLevel The message priority at which this message is to
  287. * be logged.
  288. * @since 1.7
  289. */
  290. public void log(String msg, Throwable t, int msgLevel) {
  291. if (getProject() == null) {
  292. super.log(msg, msgLevel);
  293. } else {
  294. getProject().log(this, msg, t, msgLevel);
  295. }
  296. }
  297. /**
  298. * Performs this task if it's still valid, or gets a replacement
  299. * version and performs that otherwise.
  300. *
  301. * Performing a task consists of firing a task started event,
  302. * configuring the task, executing it, and then firing task finished
  303. * event. If a runtime exception is thrown, the task finished event
  304. * is still fired, but with the exception as the cause.
  305. */
  306. public final void perform() {
  307. if (invalid) {
  308. UnknownElement ue = getReplacement();
  309. Task task = ue.getTask();
  310. task.perform();
  311. } else {
  312. getProject().fireTaskStarted(this);
  313. Throwable reason = null;
  314. try {
  315. maybeConfigure();
  316. DispatchUtils.execute(this);
  317. } catch (BuildException ex) {
  318. if (ex.getLocation() == Location.UNKNOWN_LOCATION) {
  319. ex.setLocation(getLocation());
  320. }
  321. reason = ex;
  322. throw ex;
  323. } catch (Exception ex) {
  324. reason = ex;
  325. BuildException be = new BuildException(ex);
  326. be.setLocation(getLocation());
  327. throw be;
  328. } catch (Error ex) {
  329. reason = ex;
  330. throw ex;
  331. } finally {
  332. getProject().fireTaskFinished(this, reason);
  333. }
  334. }
  335. }
  336. /**
  337. * Marks this task as invalid. Any further use of this task
  338. * will go through a replacement with the updated definition.
  339. */
  340. final void markInvalid() {
  341. invalid = true;
  342. }
  343. /**
  344. * Has this task been marked invalid?
  345. *
  346. * @return true if this task is no longer valid. A new task should be
  347. * configured in this case.
  348. *
  349. * @since Ant 1.5
  350. */
  351. protected final boolean isInvalid() {
  352. return invalid;
  353. }
  354. /**
  355. * Replacement element used if this task is invalidated.
  356. */
  357. private UnknownElement replacement;
  358. /**
  359. * Creates an UnknownElement that can be used to replace this task.
  360. * Once this has been created once, it is cached and returned by
  361. * future calls.
  362. *
  363. * @return the UnknownElement instance for the new definition of this task.
  364. */
  365. private UnknownElement getReplacement() {
  366. if (replacement == null) {
  367. replacement = new UnknownElement(taskType);
  368. replacement.setProject(getProject());
  369. replacement.setTaskType(taskType);
  370. replacement.setTaskName(taskName);
  371. replacement.setLocation(getLocation());
  372. replacement.setOwningTarget(target);
  373. replacement.setRuntimeConfigurableWrapper(wrapper);
  374. wrapper.setProxy(replacement);
  375. replaceChildren(wrapper, replacement);
  376. target.replaceChild(this, replacement);
  377. replacement.maybeConfigure();
  378. }
  379. return replacement;
  380. }
  381. /**
  382. * Recursively adds an UnknownElement instance for each child
  383. * element of replacement.
  384. *
  385. * @since Ant 1.5.1
  386. */
  387. private void replaceChildren(RuntimeConfigurable wrapper,
  388. UnknownElement parentElement) {
  389. Enumeration<RuntimeConfigurable> e = wrapper.getChildren();
  390. while (e.hasMoreElements()) {
  391. RuntimeConfigurable childWrapper = e.nextElement();
  392. UnknownElement childElement =
  393. new UnknownElement(childWrapper.getElementTag());
  394. parentElement.addChild(childElement);
  395. childElement.setProject(getProject());
  396. childElement.setRuntimeConfigurableWrapper(childWrapper);
  397. childWrapper.setProxy(childElement);
  398. replaceChildren(childWrapper, childElement);
  399. }
  400. }
  401. /**
  402. * Return the type of task.
  403. *
  404. * @return the type of task.
  405. */
  406. public String getTaskType() {
  407. return taskType;
  408. }
  409. /**
  410. * Return the runtime configurable structure for this task.
  411. *
  412. * @return the runtime structure for this task.
  413. */
  414. protected RuntimeConfigurable getWrapper() {
  415. return wrapper;
  416. }
  417. /**
  418. * Bind a task to another; use this when configuring a newly created
  419. * task to do work on behalf of another.
  420. * Project, OwningTarget, TaskName, Location and Description are all copied
  421. *
  422. * Important: this method does not call {@link Task#init()}.
  423. * If you are creating a task to delegate work to, call {@link Task#init()}
  424. * to initialize it.
  425. *
  426. * @param owner owning target
  427. * @since Ant1.7
  428. */
  429. public final void bindToOwner(Task owner) {
  430. setProject(owner.getProject());
  431. setOwningTarget(owner.getOwningTarget());
  432. setTaskName(owner.getTaskName());
  433. setDescription(owner.getDescription());
  434. setLocation(owner.getLocation());
  435. setTaskType(owner.getTaskType());
  436. }
  437. }