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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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, getWrapper());
  107. getWrapper().setProxy(realThing);
  108. if (realThing instanceof Task) {
  109. ((Task) realThing).setRuntimeConfigurableWrapper(getWrapper());
  110. }
  111. handleChildren(realThing, getWrapper());
  112. getWrapper().maybeConfigure(getProject());
  113. }
  114. /**
  115. * Handles output sent to System.out by this task or its real task.
  116. *
  117. * @param line The line of output to log. Should not be <code>null</code>.
  118. */
  119. protected void handleOutput(String line) {
  120. if (realThing instanceof Task) {
  121. ((Task) realThing).handleOutput(line);
  122. } else {
  123. super.handleOutput(line);
  124. }
  125. }
  126. /**
  127. * Handles error output sent to System.err by this task or its real task.
  128. *
  129. * @param line The error line to log. Should not be <code>null</code>.
  130. */
  131. protected void handleErrorOutput(String line) {
  132. if (realThing instanceof Task) {
  133. ((Task) realThing).handleErrorOutput(line);
  134. } else {
  135. super.handleErrorOutput(line);
  136. }
  137. }
  138. /**
  139. * Executes the real object if it's a task. If it's not a task
  140. * (e.g. a data type) then this method does nothing.
  141. */
  142. public void execute() {
  143. if (realThing == null) {
  144. // plain impossible to get here, maybeConfigure should
  145. // have thrown an exception.
  146. throw new BuildException("Could not create task of type: "
  147. + elementName, getLocation());
  148. }
  149. if (realThing instanceof Task) {
  150. ((Task) realThing).execute();
  151. }
  152. }
  153. /**
  154. * Adds a child element to this element.
  155. *
  156. * @param child The child element to add. Must not be <code>null</code>.
  157. */
  158. public void addChild(UnknownElement child) {
  159. children.addElement(child);
  160. }
  161. /**
  162. * Creates child elements, creates children of the children
  163. * (recursively), and sets attributes of the child elements.
  164. *
  165. * @param parent The configured object for the parent.
  166. * Must not be <code>null</code>.
  167. *
  168. * @param parentWrapper The wrapper containing child wrappers
  169. * to be configured. Must not be <code>null</code>
  170. * if there are any children.
  171. *
  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(getProject(), 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. }
  198. }
  199. /**
  200. * Creates a named task or data type. If the real object is a task,
  201. * it is configured up to the init() stage.
  202. *
  203. * @param ue The unknown element to create the real object for.
  204. * Must not be <code>null</code>.
  205. * @param w Ignored in this implementation.
  206. *
  207. * @return the task or data type represented by the given unknown element.
  208. */
  209. protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
  210. Object o = makeTask(ue, w, true);
  211. if (o == null) {
  212. o = getProject().createDataType(ue.getTag());
  213. }
  214. if (o == null) {
  215. throw getNotFoundException("task or type", ue.getTag());
  216. }
  217. return o;
  218. }
  219. /**
  220. * Creates a named task and configures it up to the init() stage.
  221. *
  222. * @param ue The UnknownElement to create the real task for.
  223. * Must not be <code>null</code>.
  224. * @param w Ignored.
  225. * @param onTopLevel Whether or not this is definitely trying to create
  226. * a task. If this is <code>true</code> and the
  227. * task name is not recognised, a BuildException
  228. * is thrown.
  229. *
  230. * @return the task specified by the given unknown element, or
  231. * <code>null</code> if the task name is not recognised and
  232. * onTopLevel is <code>false</code>.
  233. */
  234. protected Task makeTask(UnknownElement ue, RuntimeConfigurable w,
  235. boolean onTopLevel) {
  236. Task task = getProject().createTask(ue.getTag());
  237. if (task == null && !onTopLevel) {
  238. throw getNotFoundException("task", ue.getTag());
  239. }
  240. if (task != null) {
  241. task.setLocation(getLocation());
  242. // UnknownElement always has an associated target
  243. task.setOwningTarget(getOwningTarget());
  244. task.init();
  245. }
  246. return task;
  247. }
  248. /**
  249. * Returns a very verbose exception for when a task/data type cannot
  250. * be found.
  251. *
  252. * @param what The kind of thing being created. For example, when
  253. * a task name could not be found, this would be
  254. * <code>"task"</code>. Should not be <code>null</code>.
  255. * @param elementName The name of the element which could not be found.
  256. * Should not be <code>null</code>.
  257. *
  258. * @return a detailed description of what might have caused the problem.
  259. */
  260. protected BuildException getNotFoundException(String what,
  261. String elementName) {
  262. String lSep = System.getProperty("line.separator");
  263. String msg = "Could not create " + what + " of type: " + elementName
  264. + "." + lSep + lSep
  265. + "Ant could not find the task or a class this "
  266. + "task relies upon." + lSep + lSep
  267. + "This is common and has a number of causes; the usual " + lSep
  268. + "solutions are to read the manual pages then download and" + lSep
  269. + "install needed JAR files, or fix the build file: " + lSep
  270. + " - You have misspelt '" + elementName + "'." + lSep
  271. + " Fix: check your spelling." + lSep
  272. + " - The task needs an external JAR file to execute" + lSep
  273. + " and this is not found at the right place in the classpath." + lSep
  274. + " Fix: check the documentation for dependencies." + lSep
  275. + " Fix: declare the task." + lSep
  276. + " - The task is an Ant optional task and optional.jar is absent" + lSep
  277. + " Fix: look for optional.jar in ANT_HOME/lib, download if needed" + lSep
  278. + " - The task was not built into optional.jar as dependent" + lSep
  279. + " libraries were not found at build time." + lSep
  280. + " Fix: look in the JAR to verify, then rebuild with the needed" + lSep
  281. + " libraries, or download a release version from apache.org" + lSep
  282. + " - The build file was written for a later version of Ant" + lSep
  283. + " Fix: upgrade to at least the latest release version of Ant" + lSep
  284. + " - The task is not an Ant core or optional task " + lSep
  285. + " and needs to be declared using <taskdef>." + lSep
  286. + lSep
  287. + "Remember that for JAR files to be visible to Ant tasks implemented" + lSep
  288. + "in ANT_HOME/lib, the files must be in the same directory or on the" + lSep
  289. + "classpath" + lSep
  290. + lSep
  291. + "Please neither file bug reports on this problem, nor email the" + lSep
  292. + "Ant mailing lists, until all of these causes have been explored," + lSep
  293. + "as this is not an Ant bug.";
  294. return new BuildException(msg, getLocation());
  295. }
  296. /**
  297. * Returns the name to use in logging messages.
  298. *
  299. * @return the name to use in logging messages.
  300. */
  301. public String getTaskName() {
  302. return realThing == null || !(realThing instanceof Task) ?
  303. super.getTaskName() : ((Task) realThing).getTaskName();
  304. }
  305. /**
  306. * Returns the task instance after it has been created and if it is a task.
  307. *
  308. * @return a task instance or <code>null</code> if the real object is not
  309. * a task.
  310. */
  311. public Task getTask() {
  312. if (realThing instanceof Task) {
  313. return (Task) realThing;
  314. }
  315. return null;
  316. }
  317. }// UnknownElement