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.

ProjectHelper2.java 43 kB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  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.helper;
  18. import java.io.File;
  19. import java.io.FileInputStream;
  20. import java.io.FileNotFoundException;
  21. import java.io.InputStream;
  22. import java.io.IOException;
  23. import java.io.UnsupportedEncodingException;
  24. import java.net.URL;
  25. import java.util.HashMap;
  26. import java.util.Hashtable;
  27. import java.util.Map;
  28. import java.util.Stack;
  29. import org.xml.sax.Locator;
  30. import org.xml.sax.InputSource;
  31. import org.xml.sax.SAXParseException;
  32. import org.xml.sax.SAXException;
  33. import org.xml.sax.Attributes;
  34. import org.xml.sax.helpers.DefaultHandler;
  35. import org.apache.tools.ant.util.JAXPUtils;
  36. import org.apache.tools.ant.util.FileUtils;
  37. import org.apache.tools.ant.ProjectHelper;
  38. import org.apache.tools.ant.Project;
  39. import org.apache.tools.ant.Target;
  40. import org.apache.tools.ant.Task;
  41. import org.apache.tools.ant.RuntimeConfigurable;
  42. import org.apache.tools.ant.BuildException;
  43. import org.apache.tools.ant.Location;
  44. import org.apache.tools.ant.UnknownElement;
  45. import org.xml.sax.XMLReader;
  46. /**
  47. * Sax2 based project reader
  48. *
  49. */
  50. public class ProjectHelper2 extends ProjectHelper {
  51. /* Stateless */
  52. // singletons - since all state is in the context
  53. private static AntHandler elementHandler = new ElementHandler();
  54. private static AntHandler targetHandler = new TargetHandler();
  55. private static AntHandler mainHandler = new MainHandler();
  56. private static AntHandler projectHandler = new ProjectHandler();
  57. /**
  58. * helper for path -> URI and URI -> path conversions.
  59. */
  60. private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  61. /**
  62. * Parse an unknown element from a url
  63. *
  64. * @param project the current project
  65. * @param source the url containing the task
  66. * @return a configured task
  67. * @exception BuildException if an error occurs
  68. */
  69. public UnknownElement parseUnknownElement(Project project, URL source)
  70. throws BuildException {
  71. Target dummyTarget = new Target();
  72. dummyTarget.setProject(project);
  73. AntXMLContext context = new AntXMLContext(project);
  74. context.addTarget(dummyTarget);
  75. context.setImplicitTarget(dummyTarget);
  76. parse(context.getProject(), source,
  77. new RootHandler(context, elementHandler));
  78. Task[] tasks = dummyTarget.getTasks();
  79. if (tasks.length != 1) {
  80. throw new BuildException("No tasks defined");
  81. }
  82. return (UnknownElement) tasks[0];
  83. }
  84. /**
  85. * Parse a source xml input.
  86. *
  87. * @param project the current project
  88. * @param source the xml source
  89. * @exception BuildException if an error occurs
  90. */
  91. public void parse(Project project, Object source)
  92. throws BuildException {
  93. getImportStack().addElement(source);
  94. //System.out.println("Adding " + source);
  95. AntXMLContext context = null;
  96. context = (AntXMLContext) project.getReference("ant.parsing.context");
  97. // System.out.println("Parsing " + getImportStack().size() + " " +
  98. // context+ " " + getImportStack() );
  99. if (context == null) {
  100. context = new AntXMLContext(project);
  101. project.addReference("ant.parsing.context", context);
  102. project.addReference("ant.targets", context.getTargets());
  103. }
  104. if (getImportStack().size() > 1) {
  105. // we are in an imported file.
  106. context.setIgnoreProjectTag(true);
  107. Target currentTarget = context.getCurrentTarget();
  108. Target currentImplicit = context.getImplicitTarget();
  109. Map currentTargets = context.getCurrentTargets();
  110. try {
  111. Target newCurrent = new Target();
  112. newCurrent.setProject(project);
  113. newCurrent.setName("");
  114. context.setCurrentTarget(newCurrent);
  115. context.setCurrentTargets(new HashMap());
  116. context.setImplicitTarget(newCurrent);
  117. parse(project, source, new RootHandler(context, mainHandler));
  118. newCurrent.execute();
  119. } finally {
  120. context.setCurrentTarget(currentTarget);
  121. context.setImplicitTarget(currentImplicit);
  122. context.setCurrentTargets(currentTargets);
  123. }
  124. } else {
  125. // top level file
  126. context.setCurrentTargets(new HashMap());
  127. parse(project, source, new RootHandler(context, mainHandler));
  128. // Execute the top-level target
  129. context.getImplicitTarget().execute();
  130. }
  131. }
  132. /**
  133. * Parses the project file, configuring the project as it goes.
  134. *
  135. * @param project the current project
  136. * @param source the xml source
  137. * @param handler the root handler to use (contains the current context)
  138. * @exception BuildException if the configuration is invalid or cannot
  139. * be read
  140. */
  141. public void parse(Project project, Object source, RootHandler handler)
  142. throws BuildException {
  143. AntXMLContext context = handler.context;
  144. File buildFile = null;
  145. URL url = null;
  146. String buildFileName = null;
  147. if (source instanceof File) {
  148. buildFile = (File) source;
  149. buildFile = FILE_UTILS.normalize(buildFile.getAbsolutePath());
  150. context.setBuildFile(buildFile);
  151. buildFileName = buildFile.toString();
  152. // } else if (source instanceof InputStream ) {
  153. } else if (source instanceof URL) {
  154. url = (URL) source;
  155. buildFileName = url.toString();
  156. // } else if (source instanceof InputSource ) {
  157. } else {
  158. throw new BuildException("Source " + source.getClass().getName()
  159. + " not supported by this plugin");
  160. }
  161. InputStream inputStream = null;
  162. InputSource inputSource = null;
  163. try {
  164. /**
  165. * SAX 2 style parser used to parse the given file.
  166. */
  167. XMLReader parser = JAXPUtils.getNamespaceXMLReader();
  168. String uri = null;
  169. if (buildFile != null) {
  170. uri = FILE_UTILS.toURI(buildFile.getAbsolutePath());
  171. inputStream = new FileInputStream(buildFile);
  172. } else {
  173. inputStream = url.openStream();
  174. uri = url.toString(); // ?? OK ??
  175. }
  176. inputSource = new InputSource(inputStream);
  177. if (uri != null) {
  178. inputSource.setSystemId(uri);
  179. }
  180. project.log("parsing buildfile " + buildFileName
  181. + " with URI = " + uri, Project.MSG_VERBOSE);
  182. DefaultHandler hb = handler;
  183. parser.setContentHandler(hb);
  184. parser.setEntityResolver(hb);
  185. parser.setErrorHandler(hb);
  186. parser.setDTDHandler(hb);
  187. parser.parse(inputSource);
  188. } catch (SAXParseException exc) {
  189. Location location = new Location(exc.getSystemId(),
  190. exc.getLineNumber(), exc.getColumnNumber());
  191. Throwable t = exc.getException();
  192. if (t instanceof BuildException) {
  193. BuildException be = (BuildException) t;
  194. if (be.getLocation() == Location.UNKNOWN_LOCATION) {
  195. be.setLocation(location);
  196. }
  197. throw be;
  198. } else if (t == null) {
  199. t = exc;
  200. }
  201. throw new BuildException(exc.getMessage(), t, location);
  202. } catch (SAXException exc) {
  203. Throwable t = exc.getException();
  204. if (t instanceof BuildException) {
  205. throw (BuildException) t;
  206. } else if (t == null) {
  207. t = exc;
  208. }
  209. throw new BuildException(exc.getMessage(), t);
  210. } catch (FileNotFoundException exc) {
  211. throw new BuildException(exc);
  212. } catch (UnsupportedEncodingException exc) {
  213. throw new BuildException("Encoding of project file "
  214. + buildFileName + " is invalid.",
  215. exc);
  216. } catch (IOException exc) {
  217. throw new BuildException("Error reading project file "
  218. + buildFileName + ": " + exc.getMessage(),
  219. exc);
  220. } finally {
  221. FileUtils.close(inputStream);
  222. }
  223. }
  224. /**
  225. * The common superclass for all SAX event handlers used to parse
  226. * the configuration file.
  227. *
  228. * The context will hold all state information. At each time
  229. * there is one active handler for the current element. It can
  230. * use onStartChild() to set an alternate handler for the child.
  231. */
  232. public static class AntHandler {
  233. /**
  234. * Handles the start of an element. This base implementation does
  235. * nothing.
  236. *
  237. * @param uri the namespace URI for the tag
  238. * @param tag The name of the element being started.
  239. * Will not be <code>null</code>.
  240. * @param qname The qualified name of the element.
  241. * @param attrs Attributes of the element being started.
  242. * Will not be <code>null</code>.
  243. * @param context The context that this element is in.
  244. *
  245. * @exception SAXParseException if this method is not overridden, or in
  246. * case of error in an overridden version
  247. */
  248. public void onStartElement(String uri, String tag, String qname,
  249. Attributes attrs,
  250. AntXMLContext context)
  251. throws SAXParseException {
  252. }
  253. /**
  254. * Handles the start of an element. This base implementation just
  255. * throws an exception - you must override this method if you expect
  256. * child elements.
  257. *
  258. * @param uri The namespace uri for this element.
  259. * @param tag The name of the element being started.
  260. * Will not be <code>null</code>.
  261. * @param qname The qualified name for this element.
  262. * @param attrs Attributes of the element being started.
  263. * Will not be <code>null</code>.
  264. * @param context The current context.
  265. * @return a handler (in the derived classes)
  266. *
  267. * @exception SAXParseException if this method is not overridden, or in
  268. * case of error in an overridden version
  269. */
  270. public AntHandler onStartChild(String uri, String tag, String qname,
  271. Attributes attrs,
  272. AntXMLContext context)
  273. throws SAXParseException {
  274. throw new SAXParseException("Unexpected element \"" + qname
  275. + " \"", context.getLocator());
  276. }
  277. /**
  278. * Handle the end of a element.
  279. *
  280. * @param uri the namespace uri of the element
  281. * @param tag the tag of the element
  282. * @param qname the qualified name of the element
  283. * @param context the current context
  284. * @exception SAXParseException if an error occurs
  285. */
  286. public void onEndChild(String uri, String tag, String qname,
  287. AntXMLContext context)
  288. throws SAXParseException {
  289. }
  290. /**
  291. * This method is called when this element and all elements nested into it have been
  292. * handled. I.e., this happens at the &lt;/end_tag_of_the_element&gt;.
  293. * @param uri the namespace uri for this element
  294. * @param tag the element name
  295. * @param context the current context
  296. */
  297. public void onEndElement(String uri, String tag,
  298. AntXMLContext context) {
  299. }
  300. /**
  301. * Handles text within an element. This base implementation just
  302. * throws an exception, you must override it if you expect content.
  303. *
  304. * @param buf A character array of the text within the element.
  305. * Will not be <code>null</code>.
  306. * @param start The start element in the array.
  307. * @param count The number of characters to read from the array.
  308. * @param context The current context.
  309. *
  310. * @exception SAXParseException if this method is not overridden, or in
  311. * case of error in an overridden version
  312. */
  313. public void characters(char[] buf, int start, int count, AntXMLContext context)
  314. throws SAXParseException {
  315. String s = new String(buf, start, count).trim();
  316. if (s.length() > 0) {
  317. throw new SAXParseException("Unexpected text \"" + s
  318. + "\"", context.getLocator());
  319. }
  320. }
  321. /**
  322. * Will be called every time a namespace is reached.
  323. * It'll verify if the ns was processed, and if not load the task
  324. * definitions.
  325. * @param uri The namespace uri.
  326. */
  327. protected void checkNamespace(String uri) {
  328. }
  329. }
  330. /**
  331. * Handler for ant processing. Uses a stack of AntHandlers to
  332. * implement each element ( the original parser used a recursive behavior,
  333. * with the implicit execution stack )
  334. */
  335. public static class RootHandler extends DefaultHandler {
  336. private Stack antHandlers = new Stack();
  337. private AntHandler currentHandler = null;
  338. private AntXMLContext context;
  339. /**
  340. * Creates a new RootHandler instance.
  341. *
  342. * @param context The context for the handler.
  343. * @param rootHandler The handler for the root element.
  344. */
  345. public RootHandler(AntXMLContext context, AntHandler rootHandler) {
  346. currentHandler = rootHandler;
  347. antHandlers.push(currentHandler);
  348. this.context = context;
  349. }
  350. /**
  351. * Returns the current ant handler object.
  352. * @return the current ant handler.
  353. */
  354. public AntHandler getCurrentAntHandler() {
  355. return currentHandler;
  356. }
  357. /**
  358. * Resolves file: URIs relative to the build file.
  359. *
  360. * @param publicId The public identifier, or <code>null</code>
  361. * if none is available. Ignored in this
  362. * implementation.
  363. * @param systemId The system identifier provided in the XML
  364. * document. Will not be <code>null</code>.
  365. * @return an inputsource for this identifier
  366. */
  367. public InputSource resolveEntity(String publicId,
  368. String systemId) {
  369. context.getProject().log("resolving systemId: "
  370. + systemId, Project.MSG_VERBOSE);
  371. if (systemId.startsWith("file:")) {
  372. String path = FILE_UTILS.fromURI(systemId);
  373. File file = new File(path);
  374. if (!file.isAbsolute()) {
  375. file = FILE_UTILS.resolveFile(context.getBuildFileParent(), path);
  376. }
  377. context.getProject().log("file=" + file, Project.MSG_DEBUG);
  378. try {
  379. InputSource inputSource =
  380. new InputSource(new FileInputStream(file));
  381. inputSource.setSystemId(FILE_UTILS.toURI(file.getAbsolutePath()));
  382. return inputSource;
  383. } catch (FileNotFoundException fne) {
  384. context.getProject().log(file.getAbsolutePath()
  385. + " could not be found", Project.MSG_WARN);
  386. }
  387. }
  388. // use default if not file or file not found
  389. context.getProject().log(
  390. "could not resolve systemId", Project.MSG_DEBUG);
  391. return null;
  392. }
  393. /**
  394. * Handles the start of a project element. A project handler is created
  395. * and initialised with the element name and attributes.
  396. *
  397. * @param uri The namespace uri for this element.
  398. * @param tag The name of the element being started.
  399. * Will not be <code>null</code>.
  400. * @param qname The qualified name for this element.
  401. * @param attrs Attributes of the element being started.
  402. * Will not be <code>null</code>.
  403. *
  404. * @exception org.xml.sax.SAXParseException if the tag given is not
  405. * <code>"project"</code>
  406. */
  407. public void startElement(String uri, String tag, String qname, Attributes attrs)
  408. throws SAXParseException {
  409. AntHandler next
  410. = currentHandler.onStartChild(uri, tag, qname, attrs, context);
  411. antHandlers.push(currentHandler);
  412. currentHandler = next;
  413. currentHandler.onStartElement(uri, tag, qname, attrs, context);
  414. }
  415. /**
  416. * Sets the locator in the project helper for future reference.
  417. *
  418. * @param locator The locator used by the parser.
  419. * Will not be <code>null</code>.
  420. */
  421. public void setDocumentLocator(Locator locator) {
  422. context.setLocator(locator);
  423. }
  424. /**
  425. * Handles the end of an element. Any required clean-up is performed
  426. * by the onEndElement() method and then the original handler
  427. * is restored to the parser.
  428. *
  429. * @param uri The namespace URI for this element.
  430. * @param name The name of the element which is ending.
  431. * Will not be <code>null</code>.
  432. * @param qName The qualified name for this element.
  433. *
  434. * @exception SAXException in case of error (not thrown in
  435. * this implementation)
  436. *
  437. */
  438. public void endElement(String uri, String name, String qName) throws SAXException {
  439. currentHandler.onEndElement(uri, name, context);
  440. AntHandler prev = (AntHandler) antHandlers.pop();
  441. currentHandler = prev;
  442. if (currentHandler != null) {
  443. currentHandler.onEndChild(uri, name, qName, context);
  444. }
  445. }
  446. /**
  447. * Handle text within an element, calls currentHandler.characters.
  448. *
  449. * @param buf A character array of the test.
  450. * @param start The start offset in the array.
  451. * @param count The number of characters to read.
  452. * @exception SAXParseException if an error occurs
  453. */
  454. public void characters(char[] buf, int start, int count)
  455. throws SAXParseException {
  456. currentHandler.characters(buf, start, count, context);
  457. }
  458. /**
  459. * Start a namespace prefix to uri mapping
  460. *
  461. * @param prefix the namespace prefix
  462. * @param uri the namespace uri
  463. */
  464. public void startPrefixMapping(String prefix, String uri) {
  465. context.startPrefixMapping(prefix, uri);
  466. }
  467. /**
  468. * End a namepace prefix to uri mapping
  469. *
  470. * @param prefix the prefix that is not mapped anymore
  471. */
  472. public void endPrefixMapping(String prefix) {
  473. context.endPrefixMapping(prefix);
  474. }
  475. }
  476. /**
  477. * The main handler - it handles the &lt;project&gt; tag.
  478. *
  479. * @see org.apache.tools.ant.helper.ProjectHelper2.AntHandler
  480. */
  481. public static class MainHandler extends AntHandler {
  482. /**
  483. * Handle the project tag
  484. *
  485. * @param uri The namespace uri.
  486. * @param name The element tag.
  487. * @param qname The element qualified name.
  488. * @param attrs The attributes of the element.
  489. * @param context The current context.
  490. * @return The project handler that handles subelements of project
  491. * @exception SAXParseException if the qualified name is not "project".
  492. */
  493. public AntHandler onStartChild(String uri, String name, String qname,
  494. Attributes attrs,
  495. AntXMLContext context)
  496. throws SAXParseException {
  497. if (name.equals("project")
  498. && (uri.equals("") || uri.equals(ANT_CORE_URI))) {
  499. return ProjectHelper2.projectHandler;
  500. } else {
  501. // if (context.importlevel > 0) {
  502. // // we are in an imported file. Allow top-level <target>.
  503. // if (qname.equals( "target" ) )
  504. // return ProjectHelper2.targetHandler;
  505. // }
  506. if (name.equals(qname)) {
  507. throw new SAXParseException("Unexpected element \"{" + uri
  508. + "}" + name + "\" {" + ANT_CORE_URI + "}" + name,
  509. context.getLocator());
  510. } else {
  511. throw new SAXParseException("Unexpected element \"" + qname
  512. + "\" " + name, context.getLocator());
  513. }
  514. }
  515. }
  516. }
  517. /**
  518. * Handler for the top level "project" element.
  519. */
  520. public static class ProjectHandler extends AntHandler {
  521. /**
  522. * Initialisation routine called after handler creation
  523. * with the element name and attributes. The attributes which
  524. * this handler can deal with are: <code>"default"</code>,
  525. * <code>"name"</code>, <code>"id"</code> and <code>"basedir"</code>.
  526. *
  527. * @param uri The namespace URI for this element.
  528. * @param tag Name of the element which caused this handler
  529. * to be created. Should not be <code>null</code>.
  530. * Ignored in this implementation.
  531. * @param qname The qualified name for this element.
  532. * @param attrs Attributes of the element which caused this
  533. * handler to be created. Must not be <code>null</code>.
  534. * @param context The current context.
  535. *
  536. * @exception SAXParseException if an unexpected attribute is
  537. * encountered or if the <code>"default"</code> attribute
  538. * is missing.
  539. */
  540. public void onStartElement(String uri, String tag, String qname,
  541. Attributes attrs,
  542. AntXMLContext context)
  543. throws SAXParseException {
  544. String baseDir = null;
  545. boolean nameAttributeSet = false;
  546. Project project = context.getProject();
  547. // Set the location of the implicit target associated with the project tag
  548. context.getImplicitTarget().setLocation(
  549. new Location(context.getLocator()));
  550. /** XXX I really don't like this - the XML processor is still
  551. * too 'involved' in the processing. A better solution (IMO)
  552. * would be to create UE for Project and Target too, and
  553. * then process the tree and have Project/Target deal with
  554. * its attributes ( similar with Description ).
  555. *
  556. * If we eventually switch to ( or add support for ) DOM,
  557. * things will work smoothly - UE can be avoided almost completely
  558. * ( it could still be created on demand, for backward compatibility )
  559. */
  560. for (int i = 0; i < attrs.getLength(); i++) {
  561. String attrUri = attrs.getURI(i);
  562. if (attrUri != null
  563. && !attrUri.equals("")
  564. && !attrUri.equals(uri)) {
  565. continue; // Ignore attributes from unknown uris
  566. }
  567. String key = attrs.getLocalName(i);
  568. String value = attrs.getValue(i);
  569. if (key.equals("default")) {
  570. if (value != null && !value.equals("")) {
  571. if (!context.isIgnoringProjectTag()) {
  572. project.setDefault(value);
  573. }
  574. }
  575. } else if (key.equals("name")) {
  576. if (value != null) {
  577. context.setCurrentProjectName(value);
  578. nameAttributeSet = true;
  579. if (!context.isIgnoringProjectTag()) {
  580. project.setName(value);
  581. project.addReference(value, project);
  582. }
  583. }
  584. } else if (key.equals("id")) {
  585. if (value != null) {
  586. // What's the difference between id and name ?
  587. if (!context.isIgnoringProjectTag()) {
  588. project.addReference(value, project);
  589. }
  590. }
  591. } else if (key.equals("basedir")) {
  592. if (!context.isIgnoringProjectTag()) {
  593. baseDir = value;
  594. }
  595. } else {
  596. // XXX ignore attributes in a different NS ( maybe store them ? )
  597. throw new SAXParseException("Unexpected attribute \""
  598. + attrs.getQName(i) + "\"", context.getLocator());
  599. }
  600. }
  601. // XXX Move to Project ( so it is shared by all helpers )
  602. String antFileProp = "ant.file." + context.getCurrentProjectName();
  603. String dup = project.getProperty(antFileProp);
  604. if (dup != null && nameAttributeSet) {
  605. File dupFile = new File(dup);
  606. if (context.isIgnoringProjectTag()
  607. && !dupFile.equals(context.getBuildFile())) {
  608. project.log("Duplicated project name in import. Project "
  609. + context.getCurrentProjectName() + " defined first in "
  610. + dup + " and again in " + context.getBuildFile(),
  611. Project.MSG_WARN);
  612. }
  613. }
  614. if (context.getBuildFile() != null) {
  615. project.setUserProperty("ant.file."
  616. + context.getCurrentProjectName(),
  617. context.getBuildFile().toString());
  618. }
  619. if (context.isIgnoringProjectTag()) {
  620. // no further processing
  621. return;
  622. }
  623. // set explicitly before starting ?
  624. if (project.getProperty("basedir") != null) {
  625. project.setBasedir(project.getProperty("basedir"));
  626. } else {
  627. // Default for baseDir is the location of the build file.
  628. if (baseDir == null) {
  629. project.setBasedir(context.getBuildFileParent().getAbsolutePath());
  630. } else {
  631. // check whether the user has specified an absolute path
  632. if ((new File(baseDir)).isAbsolute()) {
  633. project.setBasedir(baseDir);
  634. } else {
  635. project.setBaseDir(FILE_UTILS.resolveFile(
  636. context.getBuildFileParent(), baseDir));
  637. }
  638. }
  639. }
  640. project.addTarget("", context.getImplicitTarget());
  641. context.setCurrentTarget(context.getImplicitTarget());
  642. }
  643. /**
  644. * Handles the start of a top-level element within the project. An
  645. * appropriate handler is created and initialised with the details
  646. * of the element.
  647. *
  648. * @param uri The namespace URI for this element.
  649. * @param name The name of the element being started.
  650. * Will not be <code>null</code>.
  651. * @param qname The qualified name for this element.
  652. * @param attrs Attributes of the element being started.
  653. * Will not be <code>null</code>.
  654. * @param context The context for this element.
  655. * @return a target or an element handler.
  656. *
  657. * @exception org.xml.sax.SAXParseException if the tag given is not
  658. * <code>"taskdef"</code>, <code>"typedef"</code>,
  659. * <code>"property"</code>, <code>"target"</code>
  660. * or a data type definition
  661. */
  662. public AntHandler onStartChild(String uri, String name, String qname,
  663. Attributes attrs,
  664. AntXMLContext context)
  665. throws SAXParseException {
  666. if (name.equals("target")
  667. && (uri.equals("") || uri.equals(ANT_CORE_URI))) {
  668. return ProjectHelper2.targetHandler;
  669. } else {
  670. return ProjectHelper2.elementHandler;
  671. }
  672. }
  673. }
  674. /**
  675. * Handler for "target" elements.
  676. */
  677. public static class TargetHandler extends AntHandler {
  678. /**
  679. * Initialisation routine called after handler creation
  680. * with the element name and attributes. The attributes which
  681. * this handler can deal with are: <code>"name"</code>,
  682. * <code>"depends"</code>, <code>"if"</code>,
  683. * <code>"unless"</code>, <code>"id"</code> and
  684. * <code>"description"</code>.
  685. *
  686. * @param uri The namespace URI for this element.
  687. * @param tag Name of the element which caused this handler
  688. * to be created. Should not be <code>null</code>.
  689. * Ignored in this implementation.
  690. * @param qname The qualified name for this element.
  691. * @param attrs Attributes of the element which caused this
  692. * handler to be created. Must not be <code>null</code>.
  693. * @param context The current context.
  694. *
  695. * @exception SAXParseException if an unexpected attribute is encountered
  696. * or if the <code>"name"</code> attribute is missing.
  697. */
  698. public void onStartElement(String uri, String tag, String qname,
  699. Attributes attrs,
  700. AntXMLContext context)
  701. throws SAXParseException {
  702. String name = null;
  703. String depends = "";
  704. Project project = context.getProject();
  705. Target target = new Target();
  706. target.setProject(project);
  707. target.setLocation(new Location(context.getLocator()));
  708. context.addTarget(target);
  709. for (int i = 0; i < attrs.getLength(); i++) {
  710. String attrUri = attrs.getURI(i);
  711. if (attrUri != null
  712. && !attrUri.equals("")
  713. && !attrUri.equals(uri)) {
  714. continue; // Ignore attributes from unknown uris
  715. }
  716. String key = attrs.getLocalName(i);
  717. String value = attrs.getValue(i);
  718. if (key.equals("name")) {
  719. name = value;
  720. if ("".equals(name)) {
  721. throw new BuildException("name attribute must "
  722. + "not be empty");
  723. }
  724. } else if (key.equals("depends")) {
  725. depends = value;
  726. } else if (key.equals("if")) {
  727. target.setIf(value);
  728. } else if (key.equals("unless")) {
  729. target.setUnless(value);
  730. } else if (key.equals("id")) {
  731. if (value != null && !value.equals("")) {
  732. context.getProject().addReference(value, target);
  733. }
  734. } else if (key.equals("description")) {
  735. target.setDescription(value);
  736. } else {
  737. throw new SAXParseException("Unexpected attribute \""
  738. + key + "\"", context.getLocator());
  739. }
  740. }
  741. if (name == null) {
  742. throw new SAXParseException("target element appears without "
  743. + "a name attribute", context.getLocator());
  744. }
  745. // Check if this target is in the current build file
  746. if (context.getCurrentTargets().get(name) != null) {
  747. throw new BuildException(
  748. "Duplicate target '" + name + "'", target.getLocation());
  749. }
  750. Hashtable projectTargets = project.getTargets();
  751. boolean usedTarget = false;
  752. // If the name has not already been defined define it
  753. if (projectTargets.containsKey(name)) {
  754. project.log("Already defined in main or a previous import, "
  755. + "ignore " + name, Project.MSG_VERBOSE);
  756. } else {
  757. target.setName(name);
  758. context.getCurrentTargets().put(name, target);
  759. project.addOrReplaceTarget(name, target);
  760. usedTarget = true;
  761. }
  762. if (depends.length() > 0) {
  763. target.setDepends(depends);
  764. }
  765. if (context.isIgnoringProjectTag() && context.getCurrentProjectName() != null
  766. && context.getCurrentProjectName().length() != 0) {
  767. // In an impored file (and not completely
  768. // ignoring the project tag)
  769. String newName = context.getCurrentProjectName()
  770. + "." + name;
  771. Target newTarget = usedTarget ? new Target(target) : target;
  772. newTarget.setName(newName);
  773. context.getCurrentTargets().put(newName, newTarget);
  774. project.addOrReplaceTarget(newName, newTarget);
  775. }
  776. }
  777. /**
  778. * Handles the start of an element within a target.
  779. *
  780. * @param uri The namespace URI for this element.
  781. * @param name The name of the element being started.
  782. * Will not be <code>null</code>.
  783. * @param qname The qualified name for this element.
  784. * @param attrs Attributes of the element being started.
  785. * Will not be <code>null</code>.
  786. * @param context The current context.
  787. * @return an element handler.
  788. *
  789. * @exception SAXParseException if an error occurs when initialising
  790. * the appropriate child handler
  791. */
  792. public AntHandler onStartChild(String uri, String name, String qname,
  793. Attributes attrs,
  794. AntXMLContext context)
  795. throws SAXParseException {
  796. return ProjectHelper2.elementHandler;
  797. }
  798. /**
  799. * Handle the end of the project, sets the current target of the
  800. * context to be the implicit target.
  801. *
  802. * @param uri The namespace URI of the element.
  803. * @param tag The name of the element.
  804. * @param context The current context.
  805. */
  806. public void onEndElement(String uri, String tag, AntXMLContext context) {
  807. context.setCurrentTarget(context.getImplicitTarget());
  808. }
  809. }
  810. /**
  811. * Handler for all project elements ( tasks, data types )
  812. */
  813. public static class ElementHandler extends AntHandler {
  814. /**
  815. * Constructor.
  816. */
  817. public ElementHandler() {
  818. }
  819. /**
  820. * Initialisation routine called after handler creation
  821. * with the element name and attributes. This configures
  822. * the element with its attributes and sets it up with
  823. * its parent container (if any). Nested elements are then
  824. * added later as the parser encounters them.
  825. *
  826. * @param uri The namespace URI for this element.
  827. * @param tag Name of the element which caused this handler
  828. * to be created. Must not be <code>null</code>.
  829. * @param qname The qualified name for this element.
  830. * @param attrs Attributes of the element which caused this
  831. * handler to be created. Must not be <code>null</code>.
  832. * @param context The current context.
  833. *
  834. * @exception SAXParseException in case of error (not thrown in
  835. * this implementation)
  836. */
  837. public void onStartElement(String uri, String tag, String qname,
  838. Attributes attrs,
  839. AntXMLContext context)
  840. throws SAXParseException {
  841. RuntimeConfigurable parentWrapper = context.currentWrapper();
  842. Object parent = null;
  843. if (parentWrapper != null) {
  844. parent = parentWrapper.getProxy();
  845. }
  846. /* UnknownElement is used for tasks and data types - with
  847. delayed eval */
  848. UnknownElement task = new UnknownElement(tag);
  849. task.setProject(context.getProject());
  850. task.setNamespace(uri);
  851. task.setQName(qname);
  852. task.setTaskType(
  853. ProjectHelper.genComponentName(task.getNamespace(), tag));
  854. task.setTaskName(qname);
  855. Location location = new Location(context.getLocator().getSystemId(),
  856. context.getLocator().getLineNumber(),
  857. context.getLocator().getColumnNumber());
  858. task.setLocation(location);
  859. task.setOwningTarget(context.getCurrentTarget());
  860. context.configureId(task, attrs);
  861. if (parent != null) {
  862. // Nested element
  863. ((UnknownElement) parent).addChild(task);
  864. } else {
  865. // Task included in a target ( including the default one ).
  866. context.getCurrentTarget().addTask(task);
  867. }
  868. // container.addTask(task);
  869. // This is a nop in UE: task.init();
  870. RuntimeConfigurable wrapper
  871. = new RuntimeConfigurable(task, task.getTaskName());
  872. for (int i = 0; i < attrs.getLength(); i++) {
  873. String name = attrs.getLocalName(i);
  874. String attrUri = attrs.getURI(i);
  875. if (attrUri != null
  876. && !attrUri.equals("")
  877. && !attrUri.equals(uri)) {
  878. name = attrUri + ":" + attrs.getQName(i);
  879. }
  880. String value = attrs.getValue(i);
  881. // PR: Hack for ant-type value
  882. // an ant-type is a component name which can
  883. // be namespaced, need to extract the name
  884. // and convert from qualified name to uri/name
  885. if (ANT_TYPE.equals(name)
  886. || (ANT_CORE_URI.equals(attrUri)
  887. && ANT_TYPE.equals(attrs.getLocalName(i)))) {
  888. name = ANT_TYPE;
  889. int index = value.indexOf(":");
  890. if (index != -1) {
  891. String prefix = value.substring(0, index);
  892. String mappedUri = context.getPrefixMapping(prefix);
  893. if (mappedUri == null) {
  894. throw new BuildException(
  895. "Unable to find XML NS prefix " + prefix);
  896. }
  897. value = ProjectHelper.genComponentName(
  898. mappedUri, value.substring(index + 1));
  899. }
  900. }
  901. wrapper.setAttribute(name, value);
  902. }
  903. if (parentWrapper != null) {
  904. parentWrapper.addChild(wrapper);
  905. }
  906. context.pushWrapper(wrapper);
  907. }
  908. /**
  909. * Adds text to the task, using the wrapper
  910. *
  911. * @param buf A character array of the text within the element.
  912. * Will not be <code>null</code>.
  913. * @param start The start element in the array.
  914. * @param count The number of characters to read from the array.
  915. * @param context The current context.
  916. *
  917. * @exception SAXParseException if the element doesn't support text
  918. *
  919. * @see ProjectHelper#addText(Project,java.lang.Object,char[],int,int)
  920. */
  921. public void characters(char[] buf, int start, int count,
  922. AntXMLContext context)
  923. throws SAXParseException {
  924. RuntimeConfigurable wrapper = context.currentWrapper();
  925. wrapper.addText(buf, start, count);
  926. }
  927. /**
  928. * Handles the start of an element within a target. Task containers
  929. * will always use another task handler, and all other tasks
  930. * will always use a nested element handler.
  931. *
  932. * @param uri The namespace URI for this element.
  933. * @param tag The name of the element being started.
  934. * Will not be <code>null</code>.
  935. * @param qname The qualified name for this element.
  936. * @param attrs Attributes of the element being started.
  937. * Will not be <code>null</code>.
  938. * @param context The current context.
  939. * @return The handler for elements.
  940. *
  941. * @exception SAXParseException if an error occurs when initialising
  942. * the appropriate child handler
  943. */
  944. public AntHandler onStartChild(String uri, String tag, String qname,
  945. Attributes attrs,
  946. AntXMLContext context)
  947. throws SAXParseException {
  948. return ProjectHelper2.elementHandler;
  949. }
  950. /**
  951. * Handles the end of the element. This pops the wrapper from
  952. * the context.
  953. *
  954. * @param uri The namespace URI for the element.
  955. * @param tag The name of the element.
  956. * @param context The current context.
  957. */
  958. public void onEndElement(String uri, String tag, AntXMLContext context) {
  959. context.popWrapper();
  960. }
  961. }
  962. }