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.

UnknownElement.java 14 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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.Vector;
  56. /**
  57. * Wrapper class that holds all the information necessary to create a task
  58. * or data type that did not exist when Ant started, or one which
  59. * has had its definition updated to use a different implementation class.
  60. *
  61. * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
  62. */
  63. public class UnknownElement extends Task {
  64. /**
  65. * Holds the name of the task/type or nested child element of a
  66. * task/type that hasn't been defined at parser time or has
  67. * been redefined since original creation.
  68. */
  69. private String elementName;
  70. /**
  71. * The real object after it has been loaded.
  72. */
  73. private Object realThing;
  74. /**
  75. * List of child elements (UnknownElements).
  76. */
  77. private Vector children = new Vector();
  78. /**
  79. * Creates an UnknownElement for the given element name.
  80. *
  81. * @param elementName The name of the unknown element.
  82. * Must not be <code>null</code>.
  83. */
  84. public UnknownElement (String elementName) {
  85. this.elementName = elementName;
  86. }
  87. /**
  88. * Returns the name of the XML element which generated this unknown
  89. * element.
  90. *
  91. * @return the name of the XML element which generated this unknown
  92. * element.
  93. */
  94. public String getTag() {
  95. return elementName;
  96. }
  97. /**
  98. * Creates the real object instance and child elements, then configures
  99. * the attributes and text of the real object. This unknown element
  100. * is then replaced with the real object in the containing target's list
  101. * of children.
  102. *
  103. * @exception BuildException if the configuration fails
  104. */
  105. public void maybeConfigure() throws BuildException {
  106. realThing = makeObject(this, wrapper);
  107. wrapper.setProxy(realThing);
  108. if (realThing instanceof Task) {
  109. ((Task) realThing).setRuntimeConfigurableWrapper(wrapper);
  110. }
  111. handleChildren(realThing, wrapper);
  112. wrapper.maybeConfigure(project);
  113. if (realThing instanceof Task) {
  114. target.replaceChild(this, (Task) realThing);
  115. } else {
  116. target.replaceChild(this, wrapper);
  117. }
  118. }
  119. /**
  120. * Handles output sent to System.out by this task or its real task.
  121. *
  122. * @param line The line of output to log. Should not be <code>null</code>.
  123. */
  124. protected void handleOutput(String line) {
  125. if (realThing instanceof Task) {
  126. ((Task)realThing).handleOutput(line);
  127. } else {
  128. super.handleOutput(line);
  129. }
  130. }
  131. /**
  132. * Handles error output sent to System.err by this task or its real task.
  133. *
  134. * @param line The error line to log. Should not be <code>null</code>.
  135. */
  136. protected void handleErrorOutput(String line) {
  137. if (realThing instanceof Task) {
  138. ((Task)realThing).handleErrorOutput(line);
  139. } else {
  140. super.handleErrorOutput(line);
  141. }
  142. }
  143. /**
  144. * Executes the real object if it's a task. If it's not a task
  145. * (e.g. a data type) then this method does nothing.
  146. */
  147. public void execute() {
  148. if (realThing == null) {
  149. // plain impossible to get here, maybeConfigure should
  150. // have thrown an exception.
  151. throw new BuildException("Could not create task of type: "
  152. + elementName, location);
  153. }
  154. if (realThing instanceof Task) {
  155. ((Task) realThing).execute();
  156. }
  157. }
  158. /**
  159. * Adds a child element to this element.
  160. *
  161. * @param child The child element to add. Must not be <code>null</code>.
  162. */
  163. public void addChild(UnknownElement child) {
  164. children.addElement(child);
  165. }
  166. /**
  167. * Creates child elements, creates children of the children
  168. * (recursively), and sets attributes of the child elements.
  169. *
  170. * @param parent The configured object for the parent.
  171. * Must not be <code>null</code>.
  172. * @exception BuildException if the children cannot be configured.
  173. */
  174. protected void handleChildren(Object parent,
  175. RuntimeConfigurable parentWrapper)
  176. throws BuildException {
  177. if (parent instanceof TaskAdapter) {
  178. parent = ((TaskAdapter) parent).getProxy();
  179. }
  180. Class parentClass = parent.getClass();
  181. IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass);
  182. for (int i = 0; i < children.size(); i++) {
  183. RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
  184. UnknownElement child = (UnknownElement) children.elementAt(i);
  185. Object realChild = null;
  186. if (parent instanceof TaskContainer) {
  187. realChild = makeTask(child, childWrapper, false);
  188. ((TaskContainer) parent).addTask((Task) realChild);
  189. } else {
  190. realChild = ih.createElement(project, parent, child.getTag());
  191. }
  192. childWrapper.setProxy(realChild);
  193. if (parent instanceof TaskContainer) {
  194. ((Task) realChild).setRuntimeConfigurableWrapper(childWrapper);
  195. }
  196. child.handleChildren(realChild, childWrapper);
  197. if (parent instanceof TaskContainer) {
  198. ((Task) realChild).maybeConfigure();
  199. }
  200. }
  201. }
  202. /**
  203. * Creates a named task or data type. If the real object is a task,
  204. * it is configured up to the init() stage.
  205. *
  206. * @param ue The unknown element to create the real object for.
  207. * Must not be <code>null</code>.
  208. * @param w Ignored in this implementation.
  209. *
  210. * @return the task or data type represented by the given unknown element.
  211. */
  212. protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
  213. Object o = makeTask(ue, w, true);
  214. if (o == null) {
  215. o = project.createDataType(ue.getTag());
  216. }
  217. if (o == null) {
  218. throw getNotFoundException("task or type", ue.getTag());
  219. }
  220. return o;
  221. }
  222. /**
  223. * Creates a named task and configures it up to the init() stage.
  224. *
  225. * @param ue The UnknownElement to create the real task for.
  226. * Must not be <code>null</code>.
  227. * @param w Ignored.
  228. * @param onTopLevel Whether or not this is definitely trying to create
  229. * a task. If this is <code>true</code> and the
  230. * task name is not recognised, a BuildException
  231. * is thrown.
  232. *
  233. * @return the task specified by the given unknown element, or
  234. * <code>null</code> if the task name is not recognised and
  235. * onTopLevel is <code>false</code>.
  236. */
  237. protected Task makeTask(UnknownElement ue, RuntimeConfigurable w,
  238. boolean onTopLevel) {
  239. Task task = project.createTask(ue.getTag());
  240. if (task == null && !onTopLevel) {
  241. throw getNotFoundException("task", ue.getTag());
  242. }
  243. if (task != null) {
  244. task.setLocation(getLocation());
  245. // UnknownElement always has an associated target
  246. task.setOwningTarget(target);
  247. task.init();
  248. }
  249. return task;
  250. }
  251. /**
  252. * Returns a very verbose exception for when a task/data type cannot
  253. * be found.
  254. *
  255. * @param what The kind of thing being created. For example, when
  256. * a task name could not be found, this would be
  257. * <code>"task"</code>. Should not be <code>null</code>.
  258. * @param elementName The name of the element which could not be found.
  259. * Should not be <code>null</code>.
  260. */
  261. protected BuildException getNotFoundException(String what,
  262. String elementName) {
  263. String lSep = System.getProperty("line.separator");
  264. String msg = "Could not create " + what + " of type: " + elementName
  265. + "." + lSep + lSep
  266. + "Ant could not find the task or a class this "
  267. + "task relies upon." + lSep + lSep
  268. + "This is common and has a number of causes; the usual " + lSep
  269. + "solutions are to read the manual pages then download and" + lSep
  270. + "install needed JAR files, or fix the build file: " + lSep
  271. + " - You have misspelt '" + elementName + "'." + lSep
  272. + " Fix: check your spelling." + lSep
  273. + " - The task needs an external JAR file to execute" + lSep
  274. + " and this is not found at the right place in the classpath." + lSep
  275. + " Fix: check the documentation for dependencies." + lSep
  276. + " Fix: declare the task." + lSep
  277. + " - The task is an Ant optional task and optional.jar is absent" + lSep
  278. + " Fix: look for optional.jar in ANT_HOME/lib, download if needed" + lSep
  279. + " - The task was not built into optional.jar as dependent" + lSep
  280. + " libraries were not found at build time." + lSep
  281. + " Fix: look in the JAR to verify, then rebuild with the needed" + lSep
  282. + " libraries, or download a release version from apache.org" + lSep
  283. + " - The build file was written for a later version of Ant" + lSep
  284. + " Fix: upgrade to at least the latest release version of Ant" + lSep
  285. + " - The task is not an Ant core or optional task " + lSep
  286. + " and needs to be declared using <taskdef>." + lSep
  287. + lSep
  288. + "Remember that for JAR files to be visible to An t tasks implemented" + lSep
  289. + "in ANT_HOME/lib, the files must be in the same directory or on the" + lSep
  290. + "classpath" + lSep
  291. + lSep
  292. + "Please neither file bug reports on this problem, nor email the" + lSep
  293. + "Ant mailing lists, until all of these causes have been explored," + lSep
  294. + "as this is not an Ant bug.";
  295. return new BuildException(msg, location);
  296. }
  297. /**
  298. * Returns the name to use in logging messages.
  299. *
  300. * @return the name to use in logging messages.
  301. */
  302. public String getTaskName() {
  303. return realThing == null || !(realThing instanceof Task) ?
  304. super.getTaskName() : ((Task) realThing).getTaskName();
  305. }
  306. /**
  307. * Returns the task instance after it has been created and if it is a task.
  308. *
  309. * @return a task instance or <code>null</code> if the real object is not
  310. * a task.
  311. */
  312. public Task getTask() {
  313. if (realThing instanceof Task) {
  314. return (Task) realThing;
  315. }
  316. return null;
  317. }
  318. }// UnknownElement