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 16 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2000-2003 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 "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. import java.io.IOException;
  57. /**
  58. * Wrapper class that holds all the information necessary to create a task
  59. * or data type that did not exist when Ant started, or one which
  60. * has had its definition updated to use a different implementation class.
  61. *
  62. * @author Stefan Bodewig
  63. */
  64. public class UnknownElement extends Task {
  65. /**
  66. * Holds the name of the task/type or nested child element of a
  67. * task/type that hasn't been defined at parser time or has
  68. * been redefined since original creation.
  69. */
  70. private String elementName;
  71. /**
  72. * The real object after it has been loaded.
  73. */
  74. private Object realThing;
  75. /**
  76. * List of child elements (UnknownElements).
  77. */
  78. private Vector children = new Vector();
  79. /**
  80. * Creates an UnknownElement for the given element name.
  81. *
  82. * @param elementName The name of the unknown element.
  83. * Must not be <code>null</code>.
  84. */
  85. public UnknownElement (String elementName) {
  86. this.elementName = elementName;
  87. }
  88. /**
  89. * Returns the name of the XML element which generated this unknown
  90. * element.
  91. *
  92. * @return the name of the XML element which generated this unknown
  93. * element.
  94. */
  95. public String getTag() {
  96. return elementName;
  97. }
  98. public RuntimeConfigurable getWrapper() {
  99. return wrapper;
  100. }
  101. /**
  102. * Creates the real object instance and child elements, then configures
  103. * the attributes and text of the real object. This unknown element
  104. * is then replaced with the real object in the containing target's list
  105. * of children.
  106. *
  107. * @exception BuildException if the configuration fails
  108. */
  109. public void maybeConfigure() throws BuildException {
  110. //ProjectComponentHelper helper=ProjectComponentHelper.getProjectComponentHelper();
  111. //realThing = helper.createProjectComponent( this, getProject(), null,
  112. // this.getTag());
  113. realThing = makeObject(this, getWrapper());
  114. getWrapper().setProxy(realThing);
  115. if (realThing instanceof Task) {
  116. Task task = (Task) realThing;
  117. task.setProject(project);
  118. task.setRuntimeConfigurableWrapper(getWrapper());
  119. task.setLocation(this.getLocation());
  120. // UnknownElement always has an associated target
  121. task.setOwningTarget(this.getOwningTarget());
  122. task.init();
  123. // For Script to work. Ugly
  124. // The reference is replaced by RuntimeConfigurable
  125. this.getOwningTarget().replaceChild(this, (Task) realThing);
  126. }
  127. handleChildren(realThing, getWrapper());
  128. // configure attributes of the object and it's children. If it is
  129. // a task container, defer the configuration till the task container
  130. // attempts to use the task
  131. getWrapper().maybeConfigure(getProject());
  132. }
  133. /**
  134. * Handles output sent to System.out by this task or its real task.
  135. *
  136. * @param line The line of output to log. Should not be <code>null</code>.
  137. */
  138. protected void handleOutput(String line) {
  139. if (realThing instanceof Task) {
  140. ((Task) realThing).handleOutput(line);
  141. } else {
  142. super.handleOutput(line);
  143. }
  144. }
  145. /**
  146. * @see Task#handleInput(byte[], int, int)
  147. *
  148. * @since Ant 1.6
  149. */
  150. protected int handleInput(byte[] buffer, int offset, int length)
  151. throws IOException {
  152. if (realThing instanceof Task) {
  153. return ((Task) realThing).handleInput(buffer, offset, length);
  154. } else {
  155. return super.handleInput(buffer, offset, length);
  156. }
  157. }
  158. /**
  159. * Handles output sent to System.out by this task or its real task.
  160. *
  161. * @param line The line of output to log. Should not be <code>null</code>.
  162. */
  163. protected void handleFlush(String line) {
  164. if (realThing instanceof Task) {
  165. ((Task) realThing).handleFlush(line);
  166. } else {
  167. super.handleFlush(line);
  168. }
  169. }
  170. /**
  171. * Handles error output sent to System.err by this task or its real task.
  172. *
  173. * @param line The error line to log. Should not be <code>null</code>.
  174. */
  175. protected void handleErrorOutput(String line) {
  176. if (realThing instanceof Task) {
  177. ((Task) realThing).handleErrorOutput(line);
  178. } else {
  179. super.handleErrorOutput(line);
  180. }
  181. }
  182. /**
  183. * Handles error output sent to System.err by this task or its real task.
  184. *
  185. * @param line The error line to log. Should not be <code>null</code>.
  186. */
  187. protected void handleErrorFlush(String line) {
  188. if (realThing instanceof Task) {
  189. ((Task) realThing).handleErrorOutput(line);
  190. } else {
  191. super.handleErrorOutput(line);
  192. }
  193. }
  194. /**
  195. * Executes the real object if it's a task. If it's not a task
  196. * (e.g. a data type) then this method does nothing.
  197. */
  198. public void execute() {
  199. if (realThing == null) {
  200. // plain impossible to get here, maybeConfigure should
  201. // have thrown an exception.
  202. throw new BuildException("Could not create task of type: "
  203. + elementName, getLocation());
  204. }
  205. if (realThing instanceof Task) {
  206. ((Task) realThing).execute();
  207. }
  208. // the task will not be reused ( a new init() will be called )
  209. // Let GC do its job
  210. realThing = null;
  211. }
  212. /**
  213. * Adds a child element to this element.
  214. *
  215. * @param child The child element to add. Must not be <code>null</code>.
  216. */
  217. public void addChild(UnknownElement child) {
  218. children.addElement(child);
  219. }
  220. /**
  221. * Creates child elements, creates children of the children
  222. * (recursively), and sets attributes of the child elements.
  223. *
  224. * @param parent The configured object for the parent.
  225. * Must not be <code>null</code>.
  226. *
  227. * @param parentWrapper The wrapper containing child wrappers
  228. * to be configured. Must not be <code>null</code>
  229. * if there are any children.
  230. *
  231. * @exception BuildException if the children cannot be configured.
  232. */
  233. protected void handleChildren(Object parent,
  234. RuntimeConfigurable parentWrapper)
  235. throws BuildException {
  236. if (parent instanceof TaskAdapter) {
  237. parent = ((TaskAdapter) parent).getProxy();
  238. }
  239. Class parentClass = parent.getClass();
  240. IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass);
  241. for (int i = 0; i < children.size(); i++) {
  242. RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
  243. UnknownElement child = (UnknownElement) children.elementAt(i);
  244. Object realChild = null;
  245. if (!ih.supportsNestedElement(child.getTag())
  246. && parent instanceof TaskContainer) {
  247. realChild = makeTask(child, childWrapper);
  248. if (realChild == null) {
  249. ih.throwNotSupported(getProject(), parent, child.getTag());
  250. }
  251. // XXX DataTypes will be wrapped or treated like normal components
  252. if (realChild instanceof Task) {
  253. Task task = (Task) realChild;
  254. ((TaskContainer) parent).addTask(task);
  255. task.setLocation(child.getLocation());
  256. // UnknownElement always has an associated target
  257. task.setOwningTarget(this.getOwningTarget());
  258. task.init();
  259. } else {
  260. // should not happen
  261. ih.throwNotSupported(getProject(), parent, child.getTag());
  262. }
  263. } else {
  264. realChild
  265. = ih.createElement(getProject(), parent, child.getTag());
  266. }
  267. childWrapper.setProxy(realChild);
  268. if (parent instanceof TaskContainer
  269. && realChild instanceof Task) {
  270. ((Task) realChild).setRuntimeConfigurableWrapper(childWrapper);
  271. }
  272. child.handleChildren(realChild, childWrapper);
  273. }
  274. }
  275. /**
  276. * Creates a named task or data type. If the real object is a task,
  277. * it is configured up to the init() stage.
  278. *
  279. * @param ue The unknown element to create the real object for.
  280. * Must not be <code>null</code>.
  281. * @param w Ignored in this implementation.
  282. *
  283. * @return the task or data type represented by the given unknown element.
  284. */
  285. protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
  286. Object o = makeTask(ue, w);
  287. if (o == null) {
  288. o = getProject().createDataType(ue.getTag());
  289. }
  290. if (o == null) {
  291. throw getNotFoundException("task or type", ue.getTag());
  292. }
  293. return o;
  294. }
  295. /**
  296. * Creates a named task and configures it up to the init() stage.
  297. *
  298. * @param ue The UnknownElement to create the real task for.
  299. * Must not be <code>null</code>.
  300. * @param w Ignored.
  301. *
  302. * @return the task specified by the given unknown element, or
  303. * <code>null</code> if the task name is not recognised.
  304. */
  305. protected Task makeTask(UnknownElement ue, RuntimeConfigurable w) {
  306. Task task = getProject().createTask(ue.getTag());
  307. if (task != null) {
  308. task.setLocation(getLocation());
  309. // UnknownElement always has an associated target
  310. task.setOwningTarget(getOwningTarget());
  311. task.init();
  312. }
  313. return task;
  314. }
  315. /**
  316. * Returns a very verbose exception for when a task/data type cannot
  317. * be found.
  318. *
  319. * @param what The kind of thing being created. For example, when
  320. * a task name could not be found, this would be
  321. * <code>"task"</code>. Should not be <code>null</code>.
  322. * @param elementName The name of the element which could not be found.
  323. * Should not be <code>null</code>.
  324. *
  325. * @return a detailed description of what might have caused the problem.
  326. */
  327. protected BuildException getNotFoundException(String what,
  328. String elementName) {
  329. String lSep = System.getProperty("line.separator");
  330. String msg = "Could not create " + what + " of type: " + elementName
  331. + "." + lSep + lSep
  332. + "Ant could not find the task or a class this "
  333. + "task relies upon." + lSep + lSep
  334. + "This is common and has a number of causes; the usual " + lSep
  335. + "solutions are to read the manual pages then download and" + lSep
  336. + "install needed JAR files, or fix the build file: " + lSep
  337. + " - You have misspelt '" + elementName + "'." + lSep
  338. + " Fix: check your spelling." + lSep
  339. + " - The task needs an external JAR file to execute" + lSep
  340. + " and this is not found at the right place in the classpath." + lSep
  341. + " Fix: check the documentation for dependencies." + lSep
  342. + " Fix: declare the task." + lSep
  343. + " - The task is an Ant optional task and optional.jar is absent" + lSep
  344. + " Fix: look for optional.jar in ANT_HOME/lib, download if needed" + lSep
  345. + " - The task was not built into optional.jar as dependent" + lSep
  346. + " libraries were not found at build time." + lSep
  347. + " Fix: look in the JAR to verify, then rebuild with the needed" + lSep
  348. + " libraries, or download a release version from apache.org" + lSep
  349. + " - The build file was written for a later version of Ant" + lSep
  350. + " Fix: upgrade to at least the latest release version of Ant" + lSep
  351. + " - The task is not an Ant core or optional task " + lSep
  352. + " and needs to be declared using <taskdef>." + lSep
  353. + lSep
  354. + "Remember that for JAR files to be visible to Ant tasks implemented" + lSep
  355. + "in ANT_HOME/lib, the files must be in the same directory or on the" + lSep
  356. + "classpath" + lSep
  357. + lSep
  358. + "Please neither file bug reports on this problem, nor email the" + lSep
  359. + "Ant mailing lists, until all of these causes have been explored," + lSep
  360. + "as this is not an Ant bug.";
  361. return new BuildException(msg, getLocation());
  362. }
  363. /**
  364. * Returns the name to use in logging messages.
  365. *
  366. * @return the name to use in logging messages.
  367. */
  368. public String getTaskName() {
  369. //return elementName;
  370. return realThing == null || !(realThing instanceof Task) ?
  371. super.getTaskName() : ((Task) realThing).getTaskName();
  372. }
  373. /**
  374. * Returns the task instance after it has been created and if it is a task.
  375. *
  376. * @return a task instance or <code>null</code> if the real object is not
  377. * a task.
  378. */
  379. public Task getTask() {
  380. if (realThing instanceof Task) {
  381. return (Task) realThing;
  382. }
  383. return null;
  384. }
  385. }// UnknownElement