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