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

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