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.

Target.java 15 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. * Copyright 2000-2006 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant;
  18. import java.util.ArrayList;
  19. import java.util.Collections;
  20. import java.util.Enumeration;
  21. import java.util.Hashtable;
  22. import java.util.Iterator;
  23. import java.util.List;
  24. import java.util.StringTokenizer;
  25. import org.apache.tools.ant.util.CollectionUtils;
  26. /**
  27. * Class to implement a target object with required parameters.
  28. *
  29. */
  30. public class Target implements TaskContainer {
  31. /** Name of this target. */
  32. private String name;
  33. /** The "if" condition to test on execution. */
  34. private String ifCondition = "";
  35. /** The "unless" condition to test on execution. */
  36. private String unlessCondition = "";
  37. /** List of targets this target is dependent on. */
  38. private List dependencies = null;
  39. /** Children of this target (tasks and data types). */
  40. private List children = new ArrayList();
  41. /** Since Ant 1.6.2 */
  42. private Location location = Location.UNKNOWN_LOCATION;
  43. /** Project this target belongs to. */
  44. private Project project;
  45. /** Description of this target, if any. */
  46. private String description = null;
  47. /** Default constructor. */
  48. public Target() {
  49. //empty
  50. }
  51. /**
  52. * Cloning constructor.
  53. * @param other the Target to clone.
  54. */
  55. public Target(Target other) {
  56. this.name = other.name;
  57. this.ifCondition = other.ifCondition;
  58. this.unlessCondition = other.unlessCondition;
  59. this.dependencies = other.dependencies;
  60. this.location = other.location;
  61. this.project = other.project;
  62. this.description = other.description;
  63. // The children are added to after this cloning
  64. this.children = other.children;
  65. }
  66. /**
  67. * Sets the project this target belongs to.
  68. *
  69. * @param project The project this target belongs to.
  70. * Must not be <code>null</code>.
  71. */
  72. public void setProject(Project project) {
  73. this.project = project;
  74. }
  75. /**
  76. * Returns the project this target belongs to.
  77. *
  78. * @return The project this target belongs to, or <code>null</code> if
  79. * the project has not been set yet.
  80. */
  81. public Project getProject() {
  82. return project;
  83. }
  84. /**
  85. * Sets the location of this target's definition.
  86. *
  87. * @param location <code>Location</code>
  88. * @since 1.6.2
  89. */
  90. public void setLocation(Location location) {
  91. this.location = location;
  92. }
  93. /**
  94. * Get the location of this target's definition.
  95. *
  96. * @return <code>Location</code>
  97. * @since 1.6.2
  98. */
  99. public Location getLocation() {
  100. return location;
  101. }
  102. /**
  103. * Sets the list of targets this target is dependent on.
  104. * The targets themselves are not resolved at this time.
  105. *
  106. * @param depS A comma-separated list of targets this target
  107. * depends on. Must not be <code>null</code>.
  108. */
  109. public void setDepends(String depS) {
  110. if (depS.length() > 0) {
  111. StringTokenizer tok =
  112. new StringTokenizer(depS, ",", true);
  113. while (tok.hasMoreTokens()) {
  114. String token = tok.nextToken().trim();
  115. // Make sure the dependency is not empty string
  116. if ("".equals(token) || ",".equals(token)) {
  117. throw new BuildException("Syntax Error: depends "
  118. + "attribute of target \"" + getName()
  119. + "\" has an empty string as dependency.");
  120. }
  121. addDependency(token);
  122. // Make sure that depends attribute does not
  123. // end in a ,
  124. if (tok.hasMoreTokens()) {
  125. token = tok.nextToken();
  126. if (!tok.hasMoreTokens() || !",".equals(token)) {
  127. throw new BuildException("Syntax Error: Depend "
  128. + "attribute for target \"" + getName()
  129. + "\" ends with a , character");
  130. }
  131. }
  132. }
  133. }
  134. }
  135. /**
  136. * Sets the name of this target.
  137. *
  138. * @param name The name of this target. Should not be <code>null</code>.
  139. */
  140. public void setName(String name) {
  141. this.name = name;
  142. }
  143. /**
  144. * Returns the name of this target.
  145. *
  146. * @return the name of this target, or <code>null</code> if the
  147. * name has not been set yet.
  148. */
  149. public String getName() {
  150. return name;
  151. }
  152. /**
  153. * Adds a task to this target.
  154. *
  155. * @param task The task to be added. Must not be <code>null</code>.
  156. */
  157. public void addTask(Task task) {
  158. children.add(task);
  159. }
  160. /**
  161. * Adds the wrapper for a data type element to this target.
  162. *
  163. * @param r The wrapper for the data type element to be added.
  164. * Must not be <code>null</code>.
  165. */
  166. public void addDataType(RuntimeConfigurable r) {
  167. children.add(r);
  168. }
  169. /**
  170. * Returns the current set of tasks to be executed by this target.
  171. *
  172. * @return an array of the tasks currently within this target
  173. */
  174. public Task[] getTasks() {
  175. List tasks = new ArrayList(children.size());
  176. Iterator it = children.iterator();
  177. while (it.hasNext()) {
  178. Object o = it.next();
  179. if (o instanceof Task) {
  180. tasks.add(o);
  181. }
  182. }
  183. return (Task[]) tasks.toArray(new Task[tasks.size()]);
  184. }
  185. /**
  186. * Adds a dependency to this target.
  187. *
  188. * @param dependency The name of a target this target is dependent on.
  189. * Must not be <code>null</code>.
  190. */
  191. public void addDependency(String dependency) {
  192. if (dependencies == null) {
  193. dependencies = new ArrayList(2);
  194. }
  195. dependencies.add(dependency);
  196. }
  197. /**
  198. * Returns an enumeration of the dependencies of this target.
  199. *
  200. * @return an enumeration of the dependencies of this target
  201. */
  202. public Enumeration getDependencies() {
  203. return (dependencies != null ? Collections.enumeration(dependencies)
  204. : new CollectionUtils.EmptyEnumeration());
  205. }
  206. /**
  207. * Does this target depend on the named target?
  208. * @param other the other named target.
  209. * @return true if the target does depend on the named target
  210. * @since Ant 1.6
  211. */
  212. public boolean dependsOn(String other) {
  213. Project p = getProject();
  214. Hashtable t = (p == null) ? null : p.getTargets();
  215. return (p != null
  216. && p.topoSort(getName(), t, false).contains(t.get(other)));
  217. }
  218. /**
  219. * Sets the "if" condition to test on execution. This is the
  220. * name of a property to test for existence - if the property
  221. * is not set, the task will not execute. The property goes
  222. * through property substitution once before testing, so if
  223. * property <code>foo</code> has value <code>bar</code>, setting
  224. * the "if" condition to <code>${foo}_x</code> will mean that the
  225. * task will only execute if property <code>bar_x</code> is set.
  226. *
  227. * @param property The property condition to test on execution.
  228. * May be <code>null</code>, in which case
  229. * no "if" test is performed.
  230. */
  231. public void setIf(String property) {
  232. ifCondition = (property == null) ? "" : property;
  233. }
  234. /**
  235. * Returns the "if" property condition of this target.
  236. *
  237. * @return the "if" property condition or <code>null</code> if no
  238. * "if" condition had been defined.
  239. * @since 1.6.2
  240. */
  241. public String getIf() {
  242. return ("".equals(ifCondition) ? null : ifCondition);
  243. }
  244. /**
  245. * Sets the "unless" condition to test on execution. This is the
  246. * name of a property to test for existence - if the property
  247. * is set, the task will not execute. The property goes
  248. * through property substitution once before testing, so if
  249. * property <code>foo</code> has value <code>bar</code>, setting
  250. * the "unless" condition to <code>${foo}_x</code> will mean that the
  251. * task will only execute if property <code>bar_x</code> isn't set.
  252. *
  253. * @param property The property condition to test on execution.
  254. * May be <code>null</code>, in which case
  255. * no "unless" test is performed.
  256. */
  257. public void setUnless(String property) {
  258. unlessCondition = (property == null) ? "" : property;
  259. }
  260. /**
  261. * Returns the "unless" property condition of this target.
  262. *
  263. * @return the "unless" property condition or <code>null</code>
  264. * if no "unless" condition had been defined.
  265. * @since 1.6.2
  266. */
  267. public String getUnless() {
  268. return ("".equals(unlessCondition) ? null : unlessCondition);
  269. }
  270. /**
  271. * Sets the description of this target.
  272. *
  273. * @param description The description for this target.
  274. * May be <code>null</code>, indicating that no
  275. * description is available.
  276. */
  277. public void setDescription(String description) {
  278. this.description = description;
  279. }
  280. /**
  281. * Returns the description of this target.
  282. *
  283. * @return the description of this target, or <code>null</code> if no
  284. * description is available.
  285. */
  286. public String getDescription() {
  287. return description;
  288. }
  289. /**
  290. * Returns the name of this target.
  291. *
  292. * @return the name of this target, or <code>null</code> if the
  293. * name has not been set yet.
  294. */
  295. public String toString() {
  296. return name;
  297. }
  298. /**
  299. * Executes the target if the "if" and "unless" conditions are
  300. * satisfied. Dependency checking should be done before calling this
  301. * method, as it does no checking of its own. If either the "if"
  302. * or "unless" test prevents this target from being executed, a verbose
  303. * message is logged giving the reason. It is recommended that clients
  304. * of this class call performTasks rather than this method so that
  305. * appropriate build events are fired.
  306. *
  307. * @exception BuildException if any of the tasks fail or if a data type
  308. * configuration fails.
  309. *
  310. * @see #performTasks()
  311. * @see #setIf(String)
  312. * @see #setUnless(String)
  313. */
  314. public void execute() throws BuildException {
  315. if (testIfCondition() && testUnlessCondition()) {
  316. for (int taskPosition = 0;
  317. taskPosition < children.size();
  318. ++taskPosition) {
  319. Object o = children.get(taskPosition);
  320. if (o instanceof Task) {
  321. Task task = (Task) o;
  322. task.perform();
  323. } else {
  324. RuntimeConfigurable r = (RuntimeConfigurable) o;
  325. r.maybeConfigure(project);
  326. }
  327. }
  328. } else if (!testIfCondition()) {
  329. project.log(this, "Skipped because property '"
  330. + project.replaceProperties(ifCondition)
  331. + "' not set.", Project.MSG_VERBOSE);
  332. } else {
  333. project.log(this, "Skipped because property '"
  334. + project.replaceProperties(unlessCondition)
  335. + "' set.", Project.MSG_VERBOSE);
  336. }
  337. }
  338. /**
  339. * Performs the tasks within this target (if the conditions are met),
  340. * firing target started/target finished messages around a call to
  341. * execute.
  342. *
  343. * @see #execute()
  344. */
  345. public final void performTasks() {
  346. RuntimeException thrown = null;
  347. project.fireTargetStarted(this);
  348. try {
  349. execute();
  350. } catch (RuntimeException exc) {
  351. thrown = exc;
  352. throw exc;
  353. } finally {
  354. project.fireTargetFinished(this, thrown);
  355. }
  356. }
  357. /**
  358. * Replaces all occurrences of the given task in the list
  359. * of children with the replacement data type wrapper.
  360. *
  361. * @param el The task to replace.
  362. * Must not be <code>null</code>.
  363. * @param o The data type wrapper to replace <code>el</code> with.
  364. */
  365. void replaceChild(Task el, RuntimeConfigurable o) {
  366. int index;
  367. while ((index = children.indexOf(el)) >= 0) {
  368. children.set(index, o);
  369. }
  370. }
  371. /**
  372. * Replaces all occurrences of the given task in the list
  373. * of children with the replacement task.
  374. *
  375. * @param el The task to replace.
  376. * Must not be <code>null</code>.
  377. * @param o The task to replace <code>el</code> with.
  378. */
  379. void replaceChild(Task el, Task o) {
  380. int index;
  381. while ((index = children.indexOf(el)) >= 0) {
  382. children.set(index, o);
  383. }
  384. }
  385. /**
  386. * Tests whether or not the "if" condition is satisfied.
  387. *
  388. * @return whether or not the "if" condition is satisfied. If no
  389. * condition (or an empty condition) has been set,
  390. * <code>true</code> is returned.
  391. *
  392. * @see #setIf(String)
  393. */
  394. private boolean testIfCondition() {
  395. if ("".equals(ifCondition)) {
  396. return true;
  397. }
  398. String test = project.replaceProperties(ifCondition);
  399. return project.getProperty(test) != null;
  400. }
  401. /**
  402. * Tests whether or not the "unless" condition is satisfied.
  403. *
  404. * @return whether or not the "unless" condition is satisfied. If no
  405. * condition (or an empty condition) has been set,
  406. * <code>true</code> is returned.
  407. *
  408. * @see #setUnless(String)
  409. */
  410. private boolean testUnlessCondition() {
  411. if ("".equals(unlessCondition)) {
  412. return true;
  413. }
  414. String test = project.replaceProperties(unlessCondition);
  415. return project.getProperty(test) == null;
  416. }
  417. }