source: release-kits/lirk3/bin/ant-installer/src/org/tp23/antinstaller/antmod/ProjectHelper3.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 41.6 KB
Line 
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
18package org.tp23.antinstaller.antmod;
19
20import java.io.File;
21import java.io.FileInputStream;
22import java.io.FileNotFoundException;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.UnsupportedEncodingException;
26import java.net.URL;
27import java.util.Hashtable;
28import java.util.Stack;
29
30import org.apache.tools.ant.BuildException;
31import org.apache.tools.ant.Location;
32import org.apache.tools.ant.Project;
33import org.apache.tools.ant.ProjectHelper;
34import org.apache.tools.ant.RuntimeConfigurable;
35import org.apache.tools.ant.Target;
36import org.apache.tools.ant.Task;
37import org.apache.tools.ant.UnknownElement;
38import org.apache.tools.ant.helper.AntXMLContext;
39import org.apache.tools.ant.util.FileUtils;
40import org.apache.tools.ant.util.JAXPUtils;
41import org.xml.sax.Attributes;
42import org.xml.sax.InputSource;
43import org.xml.sax.Locator;
44import org.xml.sax.SAXException;
45import org.xml.sax.SAXParseException;
46import org.xml.sax.XMLReader;
47import 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 */
55public 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 &lt;/end_tag_of_the_element&gt;.
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 &lt;project&gt; 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}
Note: See TracBrowser for help on using the repository browser.