KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > helper > ProjectHelper2


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.helper;
20
21 import org.apache.tools.ant.BuildException;
22 import org.apache.tools.ant.Location;
23 import org.apache.tools.ant.Project;
24 import org.apache.tools.ant.ProjectHelper;
25 import org.apache.tools.ant.RuntimeConfigurable;
26 import org.apache.tools.ant.Target;
27 import org.apache.tools.ant.Task;
28 import org.apache.tools.ant.UnknownElement;
29 import org.apache.tools.ant.util.FileUtils;
30 import org.apache.tools.ant.util.JAXPUtils;
31 import org.xml.sax.Attributes JavaDoc;
32 import org.xml.sax.InputSource JavaDoc;
33 import org.xml.sax.Locator JavaDoc;
34 import org.xml.sax.SAXException JavaDoc;
35 import org.xml.sax.SAXParseException JavaDoc;
36 import org.xml.sax.XMLReader JavaDoc;
37 import org.xml.sax.helpers.DefaultHandler JavaDoc;
38
39 import java.io.File JavaDoc;
40 import java.io.FileInputStream JavaDoc;
41 import java.io.FileNotFoundException JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.io.InputStream JavaDoc;
44 import java.io.UnsupportedEncodingException JavaDoc;
45 import java.net.URL JavaDoc;
46 import java.util.HashMap JavaDoc;
47 import java.util.Hashtable JavaDoc;
48 import java.util.Map JavaDoc;
49 import java.util.Stack JavaDoc;
50
51 /**
52  * Sax2 based project reader
53  *
54  */

55 public class ProjectHelper2 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 final FileUtils FILE_UTILS = FileUtils.getFileUtils();
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 JavaDoc 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 JavaDoc 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             Target currentImplicit = context.getImplicitTarget();
120             Map JavaDoc currentTargets = context.getCurrentTargets();
121             try {
122                 Target newCurrent = new Target();
123                 newCurrent.setProject(project);
124                 newCurrent.setName("");
125                 context.setCurrentTarget(newCurrent);
126                 context.setCurrentTargets(new HashMap JavaDoc());
127                 context.setImplicitTarget(newCurrent);
128                 parse(project, source, new RootHandler(context, mainHandler));
129                 newCurrent.execute();
130             } finally {
131                 context.setCurrentTarget(currentTarget);
132                 context.setImplicitTarget(currentImplicit);
133                 context.setCurrentTargets(currentTargets);
134             }
135         } else {
136             // top level file
137
context.setCurrentTargets(new HashMap JavaDoc());
138             parse(project, source, new RootHandler(context, mainHandler));
139             // Execute the top-level target
140
context.getImplicitTarget().execute();
141         }
142     }
143
144     /**
145      * Parses the project file, configuring the project as it goes.
146      *
147      * @param project the current project
148      * @param source the xml source
149      * @param handler the root handler to use (contains the current context)
150      * @exception BuildException if the configuration is invalid or cannot
151      * be read
152      */

153     public void parse(Project project, Object JavaDoc source, RootHandler handler)
154             throws BuildException {
155
156         AntXMLContext context = handler.context;
157
158         File JavaDoc buildFile = null;
159         URL JavaDoc url = null;
160         String JavaDoc buildFileName = null;
161
162         if (source instanceof File JavaDoc) {
163             buildFile = (File JavaDoc) source;
164             buildFile = FILE_UTILS.normalize(buildFile.getAbsolutePath());
165             context.setBuildFile(buildFile);
166             buildFileName = buildFile.toString();
167 // } else if (source instanceof InputStream ) {
168
} else if (source instanceof URL JavaDoc) {
169             url = (URL JavaDoc) source;
170             buildFileName = url.toString();
171 // } else if (source instanceof InputSource ) {
172
} else {
173             throw new BuildException("Source " + source.getClass().getName()
174                                      + " not supported by this plugin");
175         }
176
177         InputStream JavaDoc inputStream = null;
178         InputSource JavaDoc inputSource = null;
179
180
181         try {
182             /**
183              * SAX 2 style parser used to parse the given file.
184              */

185             XMLReader JavaDoc parser = JAXPUtils.getNamespaceXMLReader();
186
187             String JavaDoc uri = null;
188             if (buildFile != null) {
189                 uri = FILE_UTILS.toURI(buildFile.getAbsolutePath());
190                 inputStream = new FileInputStream JavaDoc(buildFile);
191             } else {
192                 inputStream = url.openStream();
193                 uri = url.toString(); // ?? OK ??
194
}
195
196             inputSource = new InputSource JavaDoc(inputStream);
197             if (uri != null) {
198                 inputSource.setSystemId(uri);
199             }
200             project.log("parsing buildfile " + buildFileName
201                         + " with URI = " + uri, Project.MSG_VERBOSE);
202
203             DefaultHandler JavaDoc hb = handler;
204
205             parser.setContentHandler(hb);
206             parser.setEntityResolver(hb);
207             parser.setErrorHandler(hb);
208             parser.setDTDHandler(hb);
209             parser.parse(inputSource);
210         } catch (SAXParseException JavaDoc exc) {
211             Location location = new Location(exc.getSystemId(),
212                 exc.getLineNumber(), exc.getColumnNumber());
213
214             Throwable JavaDoc t = exc.getException();
215             if (t instanceof BuildException) {
216                 BuildException be = (BuildException) t;
217                 if (be.getLocation() == Location.UNKNOWN_LOCATION) {
218                     be.setLocation(location);
219                 }
220                 throw be;
221             } else if (t == null) {
222                 t = exc;
223             }
224
225             throw new BuildException(exc.getMessage(), t, location);
226         } catch (SAXException JavaDoc exc) {
227             Throwable JavaDoc t = exc.getException();
228             if (t instanceof BuildException) {
229                 throw (BuildException) t;
230             } else if (t == null) {
231                 t = exc;
232             }
233             throw new BuildException(exc.getMessage(), t);
234         } catch (FileNotFoundException JavaDoc exc) {
235             throw new BuildException(exc);
236         } catch (UnsupportedEncodingException JavaDoc exc) {
237               throw new BuildException("Encoding of project file "
238                                        + buildFileName + " is invalid.",
239                                        exc);
240         } catch (IOException JavaDoc exc) {
241             throw new BuildException("Error reading project file "
242                                      + buildFileName + ": " + exc.getMessage(),
243                                      exc);
244         } finally {
245             FileUtils.close(inputStream);
246         }
247     }
248
249     /**
250      * Returns main handler
251      * @return main handler
252      */

253     protected static AntHandler getMainHandler() {
254         return mainHandler;
255     }
256
257     /**
258      * Sets main handler
259      * @param handler new main handler
260      */

261     protected static void setMainHandler(AntHandler handler) {
262         mainHandler = handler;
263     }
264
265     /**
266      * Returns project handler
267      * @return project handler
268      */

269     protected static AntHandler getProjectHandler() {
270         return projectHandler;
271     }
272
273     /**
274      * Sets project handler
275      * @param handler new project handler
276      */

277     protected static void setProjectHandler(AntHandler handler) {
278         projectHandler = handler;
279     }
280
281     /**
282      * Returns target handler
283      * @return target handler
284      */

285     protected static AntHandler getTargetHandler() {
286         return targetHandler;
287     }
288
289     /**
290      * Sets target handler
291      * @param handler new target handler
292      */

293     protected static void setTargetHandler(AntHandler handler) {
294         targetHandler = handler;
295     }
296
297     /**
298      * Returns element handler
299      * @return element handler
300      */

301     protected static AntHandler getElementHandler() {
302         return elementHandler;
303     }
304
305     /**
306      * Sets element handler
307      * @param handler new element handler
308      */

309     protected static void setElementHandler(AntHandler handler) {
310         elementHandler = handler;
311     }
312
313
314
315     /**
316      * The common superclass for all SAX event handlers used to parse
317      * the configuration file.
318      *
319      * The context will hold all state information. At each time
320      * there is one active handler for the current element. It can
321      * use onStartChild() to set an alternate handler for the child.
322      */

323     public static class AntHandler {
324         /**
325          * Handles the start of an element. This base implementation does
326          * nothing.
327          *
328          * @param uri the namespace URI for the tag
329          * @param tag The name of the element being started.
330          * Will not be <code>null</code>.
331          * @param qname The qualified name of the element.
332          * @param attrs Attributes of the element being started.
333          * Will not be <code>null</code>.
334          * @param context The context that this element is in.
335          *
336          * @exception SAXParseException if this method is not overridden, or in
337          * case of error in an overridden version
338          */

339         public void onStartElement(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname,
340                                    Attributes JavaDoc attrs,
341                                    AntXMLContext context)
342             throws SAXParseException JavaDoc {
343         }
344
345         /**
346          * Handles the start of an element. This base implementation just
347          * throws an exception - you must override this method if you expect
348          * child elements.
349          *
350          * @param uri The namespace uri for this element.
351          * @param tag The name of the element being started.
352          * Will not be <code>null</code>.
353          * @param qname The qualified name for this element.
354          * @param attrs Attributes of the element being started.
355          * Will not be <code>null</code>.
356          * @param context The current context.
357          * @return a handler (in the derived classes)
358          *
359          * @exception SAXParseException if this method is not overridden, or in
360          * case of error in an overridden version
361          */

362         public AntHandler onStartChild(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname,
363                                        Attributes JavaDoc attrs,
364                                        AntXMLContext context)
365             throws SAXParseException JavaDoc {
366             throw new SAXParseException JavaDoc("Unexpected element \"" + qname
367                 + " \"", context.getLocator());
368         }
369
370         /**
371          * Handle the end of a element.
372          *
373          * @param uri the namespace uri of the element
374          * @param tag the tag of the element
375          * @param qname the qualified name of the element
376          * @param context the current context
377          * @exception SAXParseException if an error occurs
378          */

379         public void onEndChild(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname,
380                                      AntXMLContext context)
381             throws SAXParseException JavaDoc {
382         }
383
384         /**
385          * This method is called when this element and all elements nested into it have been
386          * handled. I.e., this happens at the &lt;/end_tag_of_the_element&gt;.
387          * @param uri the namespace uri for this element
388          * @param tag the element name
389          * @param context the current context
390          */

391         public void onEndElement(String JavaDoc uri, String JavaDoc tag,
392                                  AntXMLContext context) {
393         }
394
395         /**
396          * Handles text within an element. This base implementation just
397          * throws an exception, you must override it if you expect content.
398          *
399          * @param buf A character array of the text within the element.
400          * Will not be <code>null</code>.
401          * @param start The start element in the array.
402          * @param count The number of characters to read from the array.
403          * @param context The current context.
404          *
405          * @exception SAXParseException if this method is not overridden, or in
406          * case of error in an overridden version
407          */

408         public void characters(char[] buf, int start, int count, AntXMLContext context)
409             throws SAXParseException JavaDoc {
410             String JavaDoc s = new String JavaDoc(buf, start, count).trim();
411
412             if (s.length() > 0) {
413                 throw new SAXParseException JavaDoc("Unexpected text \"" + s
414                     + "\"", context.getLocator());
415             }
416         }
417
418         /**
419          * Will be called every time a namespace is reached.
420          * It'll verify if the ns was processed, and if not load the task
421          * definitions.
422          * @param uri The namespace uri.
423          */

424         protected void checkNamespace(String JavaDoc uri) {
425
426         }
427     }
428
429     /**
430      * Handler for ant processing. Uses a stack of AntHandlers to
431      * implement each element ( the original parser used a recursive behavior,
432      * with the implicit execution stack )
433      */

434     public static class RootHandler extends DefaultHandler JavaDoc {
435         private Stack JavaDoc antHandlers = new Stack JavaDoc();
436         private AntHandler currentHandler = null;
437         private AntXMLContext context;
438
439         /**
440          * Creates a new RootHandler instance.
441          *
442          * @param context The context for the handler.
443          * @param rootHandler The handler for the root element.
444          */

445         public RootHandler(AntXMLContext context, AntHandler rootHandler) {
446             currentHandler = rootHandler;
447             antHandlers.push(currentHandler);
448             this.context = context;
449         }
450
451         /**
452          * Returns the current ant handler object.
453          * @return the current ant handler.
454          */

455         public AntHandler getCurrentAntHandler() {
456             return currentHandler;
457         }
458
459         /**
460          * Resolves file: URIs relative to the build file.
461          *
462          * @param publicId The public identifier, or <code>null</code>
463          * if none is available. Ignored in this
464          * implementation.
465          * @param systemId The system identifier provided in the XML
466          * document. Will not be <code>null</code>.
467          * @return an inputsource for this identifier
468          */

469         public InputSource JavaDoc resolveEntity(String JavaDoc publicId,
470                                          String JavaDoc systemId) {
471
472             context.getProject().log("resolving systemId: "
473                 + systemId, Project.MSG_VERBOSE);
474
475             if (systemId.startsWith("file:")) {
476                 String JavaDoc path = FILE_UTILS.fromURI(systemId);
477
478                 File JavaDoc file = new File JavaDoc(path);
479                 if (!file.isAbsolute()) {
480                     file = FILE_UTILS.resolveFile(context.getBuildFileParent(), path);
481                     context.getProject().log(
482                             "Warning: '" + systemId + "' in " + context.getBuildFile()
483                             + " should be expressed simply as '" + path.replace('\\', '/')
484                             + "' for compliance with other XML tools",
485                             Project.MSG_WARN);
486                 }
487                 context.getProject().log("file=" + file, Project.MSG_DEBUG);
488                 try {
489                     InputSource JavaDoc inputSource =
490                             new InputSource JavaDoc(new FileInputStream JavaDoc(file));
491                     inputSource.setSystemId(FILE_UTILS.toURI(file.getAbsolutePath()));
492                     return inputSource;
493                 } catch (FileNotFoundException JavaDoc fne) {
494                     context.getProject().log(file.getAbsolutePath()
495                         + " could not be found", Project.MSG_WARN);
496                 }
497
498             }
499             // use default if not file or file not found
500
context.getProject().log(
501                 "could not resolve systemId", Project.MSG_DEBUG);
502             return null;
503         }
504
505         /**
506          * Handles the start of a project element. A project handler is created
507          * and initialised with the element name and attributes.
508          *
509          * @param uri The namespace uri for this element.
510          * @param tag The name of the element being started.
511          * Will not be <code>null</code>.
512          * @param qname The qualified name for this element.
513          * @param attrs Attributes of the element being started.
514          * Will not be <code>null</code>.
515          *
516          * @exception org.xml.sax.SAXParseException if the tag given is not
517          * <code>"project"</code>
518          */

519         public void startElement(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname, Attributes JavaDoc attrs)
520             throws SAXParseException JavaDoc {
521             AntHandler next
522                 = currentHandler.onStartChild(uri, tag, qname, attrs, context);
523             antHandlers.push(currentHandler);
524             currentHandler = next;
525             currentHandler.onStartElement(uri, tag, qname, attrs, context);
526         }
527
528         /**
529          * Sets the locator in the project helper for future reference.
530          *
531          * @param locator The locator used by the parser.
532          * Will not be <code>null</code>.
533          */

534         public void setDocumentLocator(Locator JavaDoc locator) {
535             context.setLocator(locator);
536         }
537
538         /**
539          * Handles the end of an element. Any required clean-up is performed
540          * by the onEndElement() method and then the original handler
541          * is restored to the parser.
542          *
543          * @param uri The namespace URI for this element.
544          * @param name The name of the element which is ending.
545          * Will not be <code>null</code>.
546          * @param qName The qualified name for this element.
547          *
548          * @exception SAXException in case of error (not thrown in
549          * this implementation)
550          *
551          */

552         public void endElement(String JavaDoc uri, String JavaDoc name, String JavaDoc qName) throws SAXException JavaDoc {
553             currentHandler.onEndElement(uri, name, context);
554             AntHandler prev = (AntHandler) antHandlers.pop();
555             currentHandler = prev;
556             if (currentHandler != null) {
557                 currentHandler.onEndChild(uri, name, qName, context);
558             }
559         }
560
561         /**
562          * Handle text within an element, calls currentHandler.characters.
563          *
564          * @param buf A character array of the test.
565          * @param start The start offset in the array.
566          * @param count The number of characters to read.
567          * @exception SAXParseException if an error occurs
568          */

569         public void characters(char[] buf, int start, int count)
570             throws SAXParseException JavaDoc {
571             currentHandler.characters(buf, start, count, context);
572         }
573
574         /**
575          * Start a namespace prefix to uri mapping
576          *
577          * @param prefix the namespace prefix
578          * @param uri the namespace uri
579          */

580         public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) {
581             context.startPrefixMapping(prefix, uri);
582         }
583
584         /**
585          * End a namepace prefix to uri mapping
586          *
587          * @param prefix the prefix that is not mapped anymore
588          */

589         public void endPrefixMapping(String JavaDoc prefix) {
590             context.endPrefixMapping(prefix);
591         }
592     }
593
594     /**
595      * The main handler - it handles the &lt;project&gt; tag.
596      *
597      * @see org.apache.tools.ant.helper.ProjectHelper2.AntHandler
598      */

599     public static class MainHandler extends AntHandler {
600
601         /**
602          * Handle the project tag
603          *
604          * @param uri The namespace uri.
605          * @param name The element tag.
606          * @param qname The element qualified name.
607          * @param attrs The attributes of the element.
608          * @param context The current context.
609          * @return The project handler that handles subelements of project
610          * @exception SAXParseException if the qualified name is not "project".
611          */

612         public AntHandler onStartChild(String JavaDoc uri, String JavaDoc name, String JavaDoc qname,
613                                        Attributes JavaDoc attrs,
614                                        AntXMLContext context)
615             throws SAXParseException JavaDoc {
616             if (name.equals("project")
617                 && (uri.equals("") || uri.equals(ANT_CORE_URI))) {
618                 return ProjectHelper2.projectHandler;
619             } else {
620 // if (context.importlevel > 0) {
621
// // we are in an imported file. Allow top-level <target>.
622
// if (qname.equals( "target" ) )
623
// return ProjectHelper2.targetHandler;
624
// }
625
if (name.equals(qname)) {
626                     throw new SAXParseException JavaDoc("Unexpected element \"{" + uri
627                     + "}" + name + "\" {" + ANT_CORE_URI + "}" + name,
628                     context.getLocator());
629                 } else {
630                     throw new SAXParseException JavaDoc("Unexpected element \"" + qname
631                     + "\" " + name, context.getLocator());
632                 }
633             }
634         }
635     }
636
637     /**
638      * Handler for the top level "project" element.
639      */

640     public static class ProjectHandler extends AntHandler {
641
642         /**
643          * Initialisation routine called after handler creation
644          * with the element name and attributes. The attributes which
645          * this handler can deal with are: <code>"default"</code>,
646          * <code>"name"</code>, <code>"id"</code> and <code>"basedir"</code>.
647          *
648          * @param uri The namespace URI for this element.
649          * @param tag Name of the element which caused this handler
650          * to be created. Should not be <code>null</code>.
651          * Ignored in this implementation.
652          * @param qname The qualified name for this element.
653          * @param attrs Attributes of the element which caused this
654          * handler to be created. Must not be <code>null</code>.
655          * @param context The current context.
656          *
657          * @exception SAXParseException if an unexpected attribute is
658          * encountered or if the <code>"default"</code> attribute
659          * is missing.
660          */

661         public void onStartElement(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname,
662                                    Attributes JavaDoc attrs,
663                                    AntXMLContext context)
664             throws SAXParseException JavaDoc {
665             String JavaDoc baseDir = null;
666             boolean nameAttributeSet = false;
667
668             Project project = context.getProject();
669             // Set the location of the implicit target associated with the project tag
670
context.getImplicitTarget().setLocation(
671                 new Location(context.getLocator()));
672
673             /** XXX I really don't like this - the XML processor is still
674              * too 'involved' in the processing. A better solution (IMO)
675              * would be to create UE for Project and Target too, and
676              * then process the tree and have Project/Target deal with
677              * its attributes ( similar with Description ).
678              *
679              * If we eventually switch to ( or add support for ) DOM,
680              * things will work smoothly - UE can be avoided almost completely
681              * ( it could still be created on demand, for backward compatibility )
682              */

683
684             for (int i = 0; i < attrs.getLength(); i++) {
685                 String JavaDoc attrUri = attrs.getURI(i);
686                 if (attrUri != null
687                     && !attrUri.equals("")
688                     && !attrUri.equals(uri)) {
689                     continue; // Ignore attributes from unknown uris
690
}
691                 String JavaDoc key = attrs.getLocalName(i);
692                 String JavaDoc value = attrs.getValue(i);
693
694                 if (key.equals("default")) {
695                     if (value != null && !value.equals("")) {
696                         if (!context.isIgnoringProjectTag()) {
697                             project.setDefault(value);
698                         }
699                     }
700                 } else if (key.equals("name")) {
701                     if (value != null) {
702                         context.setCurrentProjectName(value);
703                         nameAttributeSet = true;
704                         if (!context.isIgnoringProjectTag()) {
705                             project.setName(value);
706                             project.addReference(value, project);
707                         }
708                     }
709                 } else if (key.equals("id")) {
710                     if (value != null) {
711                         // What's the difference between id and name ?
712
if (!context.isIgnoringProjectTag()) {
713                             project.addReference(value, project);
714                         }
715                     }
716                 } else if (key.equals("basedir")) {
717                     if (!context.isIgnoringProjectTag()) {
718                         baseDir = value;
719                     }
720                 } else {
721                     // XXX ignore attributes in a different NS ( maybe store them ? )
722
throw new SAXParseException JavaDoc("Unexpected attribute \""
723                         + attrs.getQName(i) + "\"", context.getLocator());
724                 }
725             }
726
727             // XXX Move to Project ( so it is shared by all helpers )
728
String JavaDoc antFileProp = "ant.file." + context.getCurrentProjectName();
729             String JavaDoc dup = project.getProperty(antFileProp);
730             if (dup != null && nameAttributeSet) {
731                 File JavaDoc dupFile = new File JavaDoc(dup);
732                 if (context.isIgnoringProjectTag()
733                     && !dupFile.equals(context.getBuildFile())) {
734                     project.log("Duplicated project name in import. Project "
735                         + context.getCurrentProjectName() + " defined first in "
736                         + dup + " and again in " + context.getBuildFile(),
737                         Project.MSG_WARN);
738                 }
739             }
740
741             if (context.getBuildFile() != null && nameAttributeSet) {
742                 project.setUserProperty("ant.file."
743                     + context.getCurrentProjectName(),
744                     context.getBuildFile().toString());
745             }
746
747             if (context.isIgnoringProjectTag()) {
748                 // no further processing
749
return;
750             }
751             // set explicitly before starting ?
752
if (project.getProperty("basedir") != null) {
753                 project.setBasedir(project.getProperty("basedir"));
754             } else {
755                 // Default for baseDir is the location of the build file.
756
if (baseDir == null) {
757                     project.setBasedir(context.getBuildFileParent().getAbsolutePath());
758                 } else {
759                     // check whether the user has specified an absolute path
760
if ((new File JavaDoc(baseDir)).isAbsolute()) {
761                         project.setBasedir(baseDir);
762                     } else {
763                         project.setBaseDir(FILE_UTILS.resolveFile(
764                                                context.getBuildFileParent(), baseDir));
765                     }
766                 }
767             }
768
769             project.addTarget("", context.getImplicitTarget());
770             context.setCurrentTarget(context.getImplicitTarget());
771         }
772
773         /**
774          * Handles the start of a top-level element within the project. An
775          * appropriate handler is created and initialised with the details
776          * of the element.
777          *
778          * @param uri The namespace URI for this element.
779          * @param name The name of the element being started.
780          * Will not be <code>null</code>.
781          * @param qname The qualified name for this element.
782          * @param attrs Attributes of the element being started.
783          * Will not be <code>null</code>.
784          * @param context The context for this element.
785          * @return a target or an element handler.
786          *
787          * @exception org.xml.sax.SAXParseException if the tag given is not
788          * <code>"taskdef"</code>, <code>"typedef"</code>,
789          * <code>"property"</code>, <code>"target"</code>
790          * or a data type definition
791          */

792         public AntHandler onStartChild(String JavaDoc uri, String JavaDoc name, String JavaDoc qname,
793                                        Attributes JavaDoc attrs,
794                                        AntXMLContext context)
795             throws SAXParseException JavaDoc {
796             if (name.equals("target")
797                 && (uri.equals("") || uri.equals(ANT_CORE_URI))) {
798                 return ProjectHelper2.targetHandler;
799             } else {
800                 return ProjectHelper2.elementHandler;
801             }
802         }
803
804     }
805
806     /**
807      * Handler for "target" elements.
808      */

809     public static class TargetHandler extends AntHandler {
810
811         /**
812          * Initialisation routine called after handler creation
813          * with the element name and attributes. The attributes which
814          * this handler can deal with are: <code>"name"</code>,
815          * <code>"depends"</code>, <code>"if"</code>,
816          * <code>"unless"</code>, <code>"id"</code> and
817          * <code>"description"</code>.
818          *
819          * @param uri The namespace URI for this element.
820          * @param tag Name of the element which caused this handler
821          * to be created. Should not be <code>null</code>.
822          * Ignored in this implementation.
823          * @param qname The qualified name for this element.
824          * @param attrs Attributes of the element which caused this
825          * handler to be created. Must not be <code>null</code>.
826          * @param context The current context.
827          *
828          * @exception SAXParseException if an unexpected attribute is encountered
829          * or if the <code>"name"</code> attribute is missing.
830          */

831         public void onStartElement(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname,
832                                    Attributes JavaDoc attrs,
833                                    AntXMLContext context)
834             throws SAXParseException JavaDoc {
835             String JavaDoc name = null;
836             String JavaDoc depends = "";
837
838             Project project = context.getProject();
839             Target target = new Target();
840             target.setProject(project);
841             target.setLocation(new Location(context.getLocator()));
842             context.addTarget(target);
843
844             for (int i = 0; i < attrs.getLength(); i++) {
845                 String JavaDoc attrUri = attrs.getURI(i);
846                 if (attrUri != null
847                     && !attrUri.equals("")
848                     && !attrUri.equals(uri)) {
849                     continue; // Ignore attributes from unknown uris
850
}
851                 String JavaDoc key = attrs.getLocalName(i);
852                 String JavaDoc value = attrs.getValue(i);
853
854                 if (key.equals("name")) {
855                     name = value;
856                     if ("".equals(name)) {
857                         throw new BuildException("name attribute must "
858                             + "not be empty");
859                     }
860                 } else if (key.equals("depends")) {
861                     depends = value;
862                 } else if (key.equals("if")) {
863                     target.setIf(value);
864                 } else if (key.equals("unless")) {
865                     target.setUnless(value);
866                 } else if (key.equals("id")) {
867                     if (value != null && !value.equals("")) {
868                         context.getProject().addReference(value, target);
869                     }
870                 } else if (key.equals("description")) {
871                     target.setDescription(value);
872                 } else {
873                     throw new SAXParseException JavaDoc("Unexpected attribute \""
874                         + key + "\"", context.getLocator());
875                 }
876             }
877
878             if (name == null) {
879                 throw new SAXParseException JavaDoc("target element appears without "
880                     + "a name attribute", context.getLocator());
881             }
882
883             // Check if this target is in the current build file
884
if (context.getCurrentTargets().get(name) != null) {
885                 throw new BuildException(
886                     "Duplicate target '" + name + "'", target.getLocation());
887             }
888
889             Hashtable JavaDoc projectTargets = project.getTargets();
890             boolean usedTarget = false;
891             // If the name has not already been defined define it
892
if (projectTargets.containsKey(name)) {
893                 project.log("Already defined in main or a previous import, "
894                             + "ignore " + name, Project.MSG_VERBOSE);
895             } else {
896                 target.setName(name);
897                 context.getCurrentTargets().put(name, target);
898                 project.addOrReplaceTarget(name, target);
899                 usedTarget = true;
900             }
901
902             if (depends.length() > 0) {
903                 target.setDepends(depends);
904             }
905
906             if (context.isIgnoringProjectTag() && context.getCurrentProjectName() != null
907                 && context.getCurrentProjectName().length() != 0) {
908                 // In an impored file (and not completely
909
// ignoring the project tag)
910
String JavaDoc newName = context.getCurrentProjectName()
911                     + "." + name;
912                 Target newTarget = usedTarget ? new Target(target) : target;
913                 newTarget.setName(newName);
914                 context.getCurrentTargets().put(newName, newTarget);
915                 project.addOrReplaceTarget(newName, newTarget);
916             }
917         }
918
919         /**
920          * Handles the start of an element within a target.
921          *
922          * @param uri The namespace URI for this element.
923          * @param name The name of the element being started.
924          * Will not be <code>null</code>.
925          * @param qname The qualified name for this element.
926          * @param attrs Attributes of the element being started.
927          * Will not be <code>null</code>.
928          * @param context The current context.
929          * @return an element handler.
930          *
931          * @exception SAXParseException if an error occurs when initialising
932          * the appropriate child handler
933          */

934         public AntHandler onStartChild(String JavaDoc uri, String JavaDoc name, String JavaDoc qname,
935                                        Attributes JavaDoc attrs,
936                                        AntXMLContext context)
937             throws SAXParseException JavaDoc {
938             return ProjectHelper2.elementHandler;
939         }
940
941         /**
942          * Handle the end of the project, sets the current target of the
943          * context to be the implicit target.
944          *
945          * @param uri The namespace URI of the element.
946          * @param tag The name of the element.
947          * @param context The current context.
948          */

949         public void onEndElement(String JavaDoc uri, String JavaDoc tag, AntXMLContext context) {
950             context.setCurrentTarget(context.getImplicitTarget());
951         }
952     }
953
954     /**
955      * Handler for all project elements ( tasks, data types )
956      */

957     public static class ElementHandler extends AntHandler {
958
959         /**
960          * Constructor.
961          */

962         public ElementHandler() {
963         }
964
965         /**
966          * Initialisation routine called after handler creation
967          * with the element name and attributes. This configures
968          * the element with its attributes and sets it up with
969          * its parent container (if any). Nested elements are then
970          * added later as the parser encounters them.
971          *
972          * @param uri The namespace URI for this element.
973          * @param tag Name of the element which caused this handler
974          * to be created. Must not be <code>null</code>.
975          * @param qname The qualified name for this element.
976          * @param attrs Attributes of the element which caused this
977          * handler to be created. Must not be <code>null</code>.
978          * @param context The current context.
979          *
980          * @exception SAXParseException in case of error (not thrown in
981          * this implementation)
982          */

983         public void onStartElement(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname,
984                                    Attributes JavaDoc attrs,
985                                    AntXMLContext context)
986             throws SAXParseException JavaDoc {
987             RuntimeConfigurable parentWrapper = context.currentWrapper();
988             Object JavaDoc parent = null;
989
990             if (parentWrapper != null) {
991                 parent = parentWrapper.getProxy();
992             }
993
994             /* UnknownElement is used for tasks and data types - with
995                delayed eval */

996             UnknownElement task = new UnknownElement(tag);
997             task.setProject(context.getProject());
998             task.setNamespace(uri);
999             task.setQName(qname);
1000            task.setTaskType(
1001                ProjectHelper.genComponentName(task.getNamespace(), tag));
1002            task.setTaskName(qname);
1003
1004            Location location = new Location(context.getLocator().getSystemId(),
1005                    context.getLocator().getLineNumber(),
1006                    context.getLocator().getColumnNumber());
1007            task.setLocation(location);
1008            task.setOwningTarget(context.getCurrentTarget());
1009
1010            if (parent != null) {
1011                // Nested element
1012
((UnknownElement) parent).addChild(task);
1013            } else {
1014                // Task included in a target ( including the default one ).
1015
context.getCurrentTarget().addTask(task);
1016            }
1017
1018            context.configureId(task, attrs);
1019
1020            // container.addTask(task);
1021
// This is a nop in UE: task.init();
1022

1023            RuntimeConfigurable wrapper
1024                = new RuntimeConfigurable(task, task.getTaskName());
1025
1026            for (int i = 0; i < attrs.getLength(); i++) {
1027                String JavaDoc name = attrs.getLocalName(i);
1028                String JavaDoc attrUri = attrs.getURI(i);
1029                if (attrUri != null
1030                    && !attrUri.equals("")
1031                    && !attrUri.equals(uri)) {
1032                    name = attrUri + ":" + attrs.getQName(i);
1033                }
1034                String JavaDoc value = attrs.getValue(i);
1035                // PR: Hack for ant-type value
1036
// an ant-type is a component name which can
1037
// be namespaced, need to extract the name
1038
// and convert from qualified name to uri/name
1039
if (ANT_TYPE.equals(name)
1040                    || (ANT_CORE_URI.equals(attrUri)
1041                        && ANT_TYPE.equals(attrs.getLocalName(i)))) {
1042                    name = ANT_TYPE;
1043                    int index = value.indexOf(":");
1044                    if (index != -1) {
1045                        String JavaDoc prefix = value.substring(0, index);
1046                        String JavaDoc mappedUri = context.getPrefixMapping(prefix);
1047                        if (mappedUri == null) {
1048                            throw new BuildException(
1049                                "Unable to find XML NS prefix " + prefix);
1050                        }
1051                        value = ProjectHelper.genComponentName(
1052                            mappedUri, value.substring(index + 1));
1053                    }
1054                }
1055                wrapper.setAttribute(name, value);
1056            }
1057
1058            if (parentWrapper != null) {
1059                parentWrapper.addChild(wrapper);
1060            }
1061
1062            context.pushWrapper(wrapper);
1063        }
1064
1065        /**
1066         * Adds text to the task, using the wrapper
1067         *
1068         * @param buf A character array of the text within the element.
1069         * Will not be <code>null</code>.
1070         * @param start The start element in the array.
1071         * @param count The number of characters to read from the array.
1072         * @param context The current context.
1073         *
1074         * @exception SAXParseException if the element doesn't support text
1075         *
1076         * @see ProjectHelper#addText(Project,java.lang.Object,char[],int,int)
1077         */

1078        public void characters(char[] buf, int start, int count,
1079                               AntXMLContext context)
1080            throws SAXParseException JavaDoc {
1081            RuntimeConfigurable wrapper = context.currentWrapper();
1082            wrapper.addText(buf, start, count);
1083        }
1084
1085        /**
1086         * Handles the start of an element within a target. Task containers
1087         * will always use another task handler, and all other tasks
1088         * will always use a nested element handler.
1089         *
1090         * @param uri The namespace URI for this element.
1091         * @param tag The name of the element being started.
1092         * Will not be <code>null</code>.
1093         * @param qname The qualified name for this element.
1094         * @param attrs Attributes of the element being started.
1095         * Will not be <code>null</code>.
1096         * @param context The current context.
1097         * @return The handler for elements.
1098         *
1099         * @exception SAXParseException if an error occurs when initialising
1100         * the appropriate child handler
1101         */

1102        public AntHandler onStartChild(String JavaDoc uri, String JavaDoc tag, String JavaDoc qname,
1103                                       Attributes JavaDoc attrs,
1104                                       AntXMLContext context)
1105            throws SAXParseException JavaDoc {
1106            return ProjectHelper2.elementHandler;
1107        }
1108
1109        /**
1110         * Handles the end of the element. This pops the wrapper from
1111         * the context.
1112         *
1113         * @param uri The namespace URI for the element.
1114         * @param tag The name of the element.
1115         * @param context The current context.
1116         */

1117        public void onEndElement(String JavaDoc uri, String JavaDoc tag, AntXMLContext context) {
1118            context.popWrapper();
1119        }
1120    }
1121}
1122
Popular Tags