KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileNotFoundException JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.UnsupportedEncodingException JavaDoc;
26 import java.util.Locale JavaDoc;
27 import org.apache.tools.ant.BuildException;
28 import org.apache.tools.ant.IntrospectionHelper;
29 import org.apache.tools.ant.Location;
30 import org.apache.tools.ant.Project;
31 import org.apache.tools.ant.ProjectHelper;
32 import org.apache.tools.ant.RuntimeConfigurable;
33 import org.apache.tools.ant.Target;
34 import org.apache.tools.ant.Task;
35 import org.apache.tools.ant.TypeAdapter;
36 import org.apache.tools.ant.TaskContainer;
37 import org.apache.tools.ant.UnknownElement;
38 import org.apache.tools.ant.util.FileUtils;
39 import org.apache.tools.ant.util.JAXPUtils;
40 import org.xml.sax.AttributeList JavaDoc;
41 import org.xml.sax.DocumentHandler JavaDoc;
42 import org.xml.sax.HandlerBase JavaDoc;
43 import org.xml.sax.InputSource JavaDoc;
44 import org.xml.sax.Locator JavaDoc;
45 import org.xml.sax.SAXException JavaDoc;
46 import org.xml.sax.SAXParseException JavaDoc;
47 import org.xml.sax.helpers.XMLReaderAdapter JavaDoc;
48
49 /**
50  * Original helper.
51  *
52  */

53 public class ProjectHelperImpl extends ProjectHelper {
54
55     /**
56      * helper for path -> URI and URI -> path conversions.
57      */

58     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
59
60     /**
61      * SAX 1 style parser used to parse the given file. This may
62      * in fact be a SAX 2 XMLReader wrapped in an XMLReaderAdapter.
63      */

64     private org.xml.sax.Parser JavaDoc parser;
65
66     /** The project to configure. */
67     private Project project;
68     /** The configuration file to parse. */
69     private File JavaDoc buildFile;
70     /**
71      * Parent directory of the build file. Used for resolving entities
72      * and setting the project's base directory.
73      */

74     private File JavaDoc buildFileParent;
75     /**
76      * Locator for the configuration file parser.
77      * Used for giving locations of errors etc.
78      */

79     private Locator JavaDoc locator;
80     /**
81      * Target that all other targets will depend upon implicitly.
82      *
83      * <p>This holds all tasks and data type definitions that have
84      * been placed outside of targets.</p>
85      */

86     private Target implicitTarget = new Target();
87
88     /**
89      * default constructor
90      */

91     public ProjectHelperImpl() {
92         implicitTarget.setName("");
93     }
94
95     /**
96      * Parses the project file, configuring the project as it goes.
97      *
98      * @param project project instance to be configured.
99      * @param source the source from which the project is read.
100      * @exception BuildException if the configuration is invalid or cannot
101      * be read.
102      */

103     public void parse(Project project, Object JavaDoc source) throws BuildException {
104         if (!(source instanceof File JavaDoc)) {
105             throw new BuildException("Only File source supported by "
106                 + "default plugin");
107         }
108         File JavaDoc bFile = (File JavaDoc) source;
109         FileInputStream JavaDoc inputStream = null;
110         InputSource JavaDoc inputSource = null;
111
112         this.project = project;
113         this.buildFile = new File JavaDoc(bFile.getAbsolutePath());
114         buildFileParent = new File JavaDoc(this.buildFile.getParent());
115
116         try {
117             try {
118                 parser = JAXPUtils.getParser();
119             } catch (BuildException e) {
120                 parser = new XMLReaderAdapter JavaDoc(JAXPUtils.getXMLReader());
121             }
122
123
124             String JavaDoc uri = FILE_UTILS.toURI(bFile.getAbsolutePath());
125             inputStream = new FileInputStream JavaDoc(bFile);
126             inputSource = new InputSource JavaDoc(inputStream);
127             inputSource.setSystemId(uri);
128             project.log("parsing buildfile " + bFile + " with URI = "
129                 + uri, Project.MSG_VERBOSE);
130             HandlerBase JavaDoc hb = new RootHandler(this);
131             parser.setDocumentHandler(hb);
132             parser.setEntityResolver(hb);
133             parser.setErrorHandler(hb);
134             parser.setDTDHandler(hb);
135             parser.parse(inputSource);
136         } catch (SAXParseException JavaDoc exc) {
137             Location location =
138                 new Location(exc.getSystemId(), exc.getLineNumber(),
139                     exc.getColumnNumber());
140
141             Throwable JavaDoc t = exc.getException();
142             if (t instanceof BuildException) {
143                 BuildException be = (BuildException) t;
144                 if (be.getLocation() == Location.UNKNOWN_LOCATION) {
145                     be.setLocation(location);
146                 }
147                 throw be;
148             }
149
150             throw new BuildException(exc.getMessage(), t, location);
151         } catch (SAXException JavaDoc exc) {
152             Throwable JavaDoc t = exc.getException();
153             if (t instanceof BuildException) {
154                 throw (BuildException) t;
155             }
156             throw new BuildException(exc.getMessage(), t);
157         } catch (FileNotFoundException JavaDoc exc) {
158             throw new BuildException(exc);
159         } catch (UnsupportedEncodingException JavaDoc exc) {
160             throw new BuildException("Encoding of project file is invalid.",
161                                      exc);
162         } catch (IOException JavaDoc exc) {
163             throw new BuildException("Error reading project file: "
164                                      + exc.getMessage(), exc);
165         } finally {
166             FileUtils.close(inputStream);
167         }
168     }
169
170     /**
171      * The common superclass for all SAX event handlers used to parse
172      * the configuration file. Each method just throws an exception,
173      * so subclasses should override what they can handle.
174      *
175      * Each type of XML element (task, target, etc.) in Ant has
176      * a specific subclass.
177      *
178      * In the constructor, this class takes over the handling of SAX
179      * events from the parent handler and returns
180      * control back to the parent in the endElement method.
181      */

182     static class AbstractHandler extends HandlerBase JavaDoc {
183         // CheckStyle:VisibilityModifier OFF - bc
184

185         /**
186          * Previous handler for the document.
187          * When the next element is finished, control returns
188          * to this handler.
189          */

190         protected DocumentHandler JavaDoc parentHandler;
191
192         /** Helper impl. With non-static internal classes, the compiler will generate
193             this automatically - but this will fail with some compilers ( reporting
194             "Expecting to find object/array on stack" ). If we pass it
195             explicitly it'll work with more compilers.
196         */

197         ProjectHelperImpl helperImpl;
198         // CheckStyle:VisibilityModifier ON
199

200         /**
201          * Creates a handler and sets the parser to use it
202          * for the current element.
203          *
204          * @param helperImpl the ProjectHelperImpl instance associated
205          * with this handler.
206          *
207          * @param parentHandler The handler which should be restored to the
208          * parser at the end of the element.
209          * Must not be <code>null</code>.
210          */

211         public AbstractHandler(ProjectHelperImpl helperImpl, DocumentHandler JavaDoc parentHandler) {
212             this.parentHandler = parentHandler;
213             this.helperImpl = helperImpl;
214
215             // Start handling SAX events
216
helperImpl.parser.setDocumentHandler(this);
217         }
218
219         /**
220          * Handles the start of an element. This base implementation just
221          * throws an exception.
222          *
223          * @param tag The name of the element being started.
224          * Will not be <code>null</code>.
225          * @param attrs Attributes of the element being started.
226          * Will not be <code>null</code>.
227          *
228          * @exception SAXParseException if this method is not overridden, or in
229          * case of error in an overridden version
230          */

231         public void startElement(String JavaDoc tag, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
232             throw new SAXParseException JavaDoc("Unexpected element \"" + tag + "\"", helperImpl.locator);
233         }
234
235         /**
236          * Handles text within an element. This base implementation just
237          * throws an exception.
238          *
239          * @param buf A character array of the text within the element.
240          * Will not be <code>null</code>.
241          * @param start The start element in the array.
242          * @param count The number of characters to read from the array.
243          *
244          * @exception SAXParseException if this method is not overridden, or in
245          * case of error in an overridden version
246          */

247         public void characters(char[] buf, int start, int count) throws SAXParseException JavaDoc {
248             String JavaDoc s = new String JavaDoc(buf, start, count).trim();
249
250             if (s.length() > 0) {
251                 throw new SAXParseException JavaDoc("Unexpected text \"" + s + "\"", helperImpl.locator);
252             }
253         }
254
255         /**
256          * Handles the end of an element. Any required clean-up is performed
257          * by the finished() method and then the original handler is restored to
258          * the parser.
259          *
260          * @param name The name of the element which is ending.
261          * Will not be <code>null</code>.
262          *
263          * @exception SAXException in case of error (not thrown in
264          * this implementation)
265          */

266         public void endElement(String JavaDoc name) throws SAXException JavaDoc {
267             // Let parent resume handling SAX events
268
helperImpl.parser.setDocumentHandler(parentHandler);
269         }
270     }
271
272     /**
273      * Handler for the root element. Its only child must be the "project" element.
274      */

275     static class RootHandler extends HandlerBase JavaDoc {
276         // CheckStyle:VisibilityModifier OFF - bc
277
ProjectHelperImpl helperImpl;
278         // CheckStyle:VisibilityModifier ON
279

280         public RootHandler(ProjectHelperImpl helperImpl) {
281             this.helperImpl = helperImpl;
282         }
283
284         /**
285          * Resolves file: URIs relative to the build file.
286          *
287          * @param publicId The public identifier, or <code>null</code>
288          * if none is available. Ignored in this
289          * implementation.
290          * @param systemId The system identifier provided in the XML
291          * document. Will not be <code>null</code>.
292          */

293         public InputSource JavaDoc resolveEntity(String JavaDoc publicId,
294                                          String JavaDoc systemId) {
295
296             helperImpl.project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
297
298             if (systemId.startsWith("file:")) {
299                 String JavaDoc path = FILE_UTILS.fromURI(systemId);
300
301                 File JavaDoc file = new File JavaDoc(path);
302                 if (!file.isAbsolute()) {
303                     file = FILE_UTILS.resolveFile(helperImpl.buildFileParent, path);
304                     helperImpl.project.log(
305                             "Warning: '" + systemId + "' in " + helperImpl.buildFile
306                             + " should be expressed simply as '" + path.replace('\\', '/')
307                             + "' for compliance with other XML tools",
308                             Project.MSG_WARN);
309                 }
310                 try {
311                     InputSource JavaDoc inputSource = new InputSource JavaDoc(new FileInputStream JavaDoc(file));
312                     inputSource.setSystemId(FILE_UTILS.toURI(file.getAbsolutePath()));
313                     return inputSource;
314                 } catch (FileNotFoundException JavaDoc fne) {
315                     helperImpl.project.log(file.getAbsolutePath() + " could not be found",
316                                 Project.MSG_WARN);
317                 }
318             }
319             // use default if not file or file not found
320
return null;
321         }
322
323         /**
324          * Handles the start of a project element. A project handler is created
325          * and initialised with the element name and attributes.
326          *
327          * @param tag The name of the element being started.
328          * Will not be <code>null</code>.
329          * @param attrs Attributes of the element being started.
330          * Will not be <code>null</code>.
331          *
332          * @exception SAXParseException if the tag given is not
333          * <code>"project"</code>
334          */

335         public void startElement(String JavaDoc tag, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
336             if (tag.equals("project")) {
337                 new ProjectHandler(helperImpl, this).init(tag, attrs);
338             } else {
339                 throw new SAXParseException JavaDoc("Config file is not of expected "
340                     + "XML type", helperImpl.locator);
341             }
342         }
343
344         /**
345          * Sets the locator in the project helper for future reference.
346          *
347          * @param locator The locator used by the parser.
348          * Will not be <code>null</code>.
349          */

350         public void setDocumentLocator(Locator JavaDoc locator) {
351             helperImpl.locator = locator;
352         }
353     }
354
355     /**
356      * Handler for the top level "project" element.
357      */

358     static class ProjectHandler extends AbstractHandler {
359
360         /**
361          * Constructor which just delegates to the superconstructor.
362          *
363          * @param parentHandler The handler which should be restored to the
364          * parser at the end of the element.
365          * Must not be <code>null</code>.
366          */

367         public ProjectHandler(ProjectHelperImpl helperImpl, DocumentHandler JavaDoc parentHandler) {
368             super(helperImpl, parentHandler);
369         }
370
371         /**
372          * Initialisation routine called after handler creation
373          * with the element name and attributes. The attributes which
374          * this handler can deal with are: <code>"default"</code>,
375          * <code>"name"</code>, <code>"id"</code> and <code>"basedir"</code>.
376          *
377          * @param tag Name of the element which caused this handler
378          * to be created. Should not be <code>null</code>.
379          * Ignored in this implementation.
380          * @param attrs Attributes of the element which caused this
381          * handler to be created. Must not be <code>null</code>.
382          *
383          * @exception SAXParseException if an unexpected attribute is
384          * encountered or if the <code>"default"</code> attribute
385          * is missing.
386          */

387         public void init(String JavaDoc tag, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
388             String JavaDoc def = null;
389             String JavaDoc name = null;
390             String JavaDoc id = null;
391             String JavaDoc baseDir = null;
392
393             for (int i = 0; i < attrs.getLength(); i++) {
394                 String JavaDoc key = attrs.getName(i);
395                 String JavaDoc value = attrs.getValue(i);
396
397                 if (key.equals("default")) {
398                     def = value;
399                 } else if (key.equals("name")) {
400                     name = value;
401                 } else if (key.equals("id")) {
402                     id = value;
403                 } else if (key.equals("basedir")) {
404                     baseDir = value;
405                 } else {
406                     throw new SAXParseException JavaDoc("Unexpected attribute \"" + attrs.getName(i) + "\"",
407                                                 helperImpl.locator);
408                 }
409             }
410
411             if (def != null && !def.equals("")) {
412                 helperImpl.project.setDefaultTarget(def);
413             } else {
414                 throw new BuildException("The default attribute is required");
415             }
416
417             if (name != null) {
418                 helperImpl.project.setName(name);
419                 helperImpl.project.addReference(name, helperImpl.project);
420             }
421
422             if (id != null) {
423                 helperImpl.project.addReference(id, helperImpl.project);
424             }
425
426             if (helperImpl.project.getProperty("basedir") != null) {
427                 helperImpl.project.setBasedir(helperImpl.project.getProperty("basedir"));
428             } else {
429                 if (baseDir == null) {
430                     helperImpl.project.setBasedir(helperImpl.buildFileParent.getAbsolutePath());
431                 } else {
432                     // check whether the user has specified an absolute path
433
if ((new File JavaDoc(baseDir)).isAbsolute()) {
434                         helperImpl.project.setBasedir(baseDir);
435                     } else {
436                         File JavaDoc resolvedBaseDir = FILE_UTILS.resolveFile(
437                                 helperImpl.buildFileParent, baseDir);
438                         helperImpl.project.setBaseDir(resolvedBaseDir);
439                     }
440                 }
441             }
442
443             helperImpl.project.addTarget("", helperImpl.implicitTarget);
444         }
445
446         /**
447          * Handles the start of a top-level element within the project. An
448          * appropriate handler is created and initialised with the details
449          * of the element.
450          *
451          * @param name The name of the element being started.
452          * Will not be <code>null</code>.
453          * @param attrs Attributes of the element being started.
454          * Will not be <code>null</code>.
455          *
456          * @exception SAXParseException if the tag given is not
457          * <code>"taskdef"</code>, <code>"typedef"</code>,
458          * <code>"property"</code>, <code>"target"</code>
459          * or a data type definition
460          */

461         public void startElement(String JavaDoc name, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
462             if (name.equals("target")) {
463                 handleTarget(name, attrs);
464             } else {
465                 handleElement(helperImpl, this, helperImpl.implicitTarget,
466                               name, attrs);
467             }
468         }
469
470         /**
471          * Handles a target definition element by creating a target handler
472          * and initialising is with the details of the element.
473          *
474          * @param tag The name of the element to be handled.
475          * Will not be <code>null</code>.
476          * @param attrs Attributes of the element to be handled.
477          * Will not be <code>null</code>.
478          *
479          * @exception SAXParseException if an error occurs initialising
480          * the handler
481          */

482         private void handleTarget(String JavaDoc tag, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
483             new TargetHandler(helperImpl, this).init(tag, attrs);
484         }
485
486     }
487
488     /**
489      * Handler for "target" elements.
490      */

491     static class TargetHandler extends AbstractHandler {
492         private Target target;
493
494         /**
495          * Constructor which just delegates to the superconstructor.
496          *
497          * @param parentHandler The handler which should be restored to the
498          * parser at the end of the element.
499          * Must not be <code>null</code>.
500          */

501         public TargetHandler(ProjectHelperImpl helperImpl, DocumentHandler JavaDoc parentHandler) {
502             super(helperImpl, parentHandler);
503         }
504
505         /**
506          * Initialisation routine called after handler creation
507          * with the element name and attributes. The attributes which
508          * this handler can deal with are: <code>"name"</code>,
509          * <code>"depends"</code>, <code>"if"</code>,
510          * <code>"unless"</code>, <code>"id"</code> and
511          * <code>"description"</code>.
512          *
513          * @param tag Name of the element which caused this handler
514          * to be created. Should not be <code>null</code>.
515          * Ignored in this implementation.
516          * @param attrs Attributes of the element which caused this
517          * handler to be created. Must not be <code>null</code>.
518          *
519          * @exception SAXParseException if an unexpected attribute is encountered
520          * or if the <code>"name"</code> attribute is missing.
521          */

522         public void init(String JavaDoc tag, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
523             String JavaDoc name = null;
524             String JavaDoc depends = "";
525             String JavaDoc ifCond = null;
526             String JavaDoc unlessCond = null;
527             String JavaDoc id = null;
528             String JavaDoc description = null;
529
530             for (int i = 0; i < attrs.getLength(); i++) {
531                 String JavaDoc key = attrs.getName(i);
532                 String JavaDoc value = attrs.getValue(i);
533
534                 if (key.equals("name")) {
535                     name = value;
536                     if (name.equals("")) {
537                         throw new BuildException("name attribute must not"
538                                                  + " be empty",
539                                                  new Location(helperImpl.locator));
540                     }
541                 } else if (key.equals("depends")) {
542                     depends = value;
543                 } else if (key.equals("if")) {
544                     ifCond = value;
545                 } else if (key.equals("unless")) {
546                     unlessCond = value;
547                 } else if (key.equals("id")) {
548                     id = value;
549                 } else if (key.equals("description")) {
550                     description = value;
551                 } else {
552                     throw new SAXParseException JavaDoc("Unexpected attribute \""
553                         + key + "\"", helperImpl.locator);
554                 }
555             }
556
557             if (name == null) {
558                 throw new SAXParseException JavaDoc("target element appears without a name attribute",
559                                             helperImpl.locator);
560             }
561
562             target = new Target();
563
564             // implicit target must be first on dependency list
565
target.addDependency("");
566
567             target.setName(name);
568             target.setIf(ifCond);
569             target.setUnless(unlessCond);
570             target.setDescription(description);
571             helperImpl.project.addTarget(name, target);
572
573             if (id != null && !id.equals("")) {
574                 helperImpl.project.addReference(id, target);
575             }
576
577             // take care of dependencies
578

579             if (depends.length() > 0) {
580                 target.setDepends(depends);
581             }
582         }
583
584         /**
585          * Handles the start of an element within a target.
586          *
587          * @param name The name of the element being started.
588          * Will not be <code>null</code>.
589          * @param attrs Attributes of the element being started.
590          * Will not be <code>null</code>.
591          *
592          * @exception SAXParseException if an error occurs when initialising
593          * the appropriate child handler
594          */

595         public void startElement(String JavaDoc name, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
596             handleElement(helperImpl, this, target, name, attrs);
597         }
598     }
599
600     /**
601      * Start a new DataTypeHandler if element is known to be a
602      * data-type and a TaskHandler otherwise.
603      *
604      * <p>Factored out of TargetHandler.</p>
605      *
606      * @since Ant 1.6
607      */

608     private static void handleElement(ProjectHelperImpl helperImpl,
609                                       DocumentHandler JavaDoc parent,
610                                       Target target, String JavaDoc elementName,
611                                       AttributeList JavaDoc attrs)
612         throws SAXParseException JavaDoc {
613         if (elementName.equals("description")) {
614             new DescriptionHandler(helperImpl, parent);
615         } else if (helperImpl.project.getDataTypeDefinitions()
616                    .get(elementName) != null) {
617             new DataTypeHandler(helperImpl, parent, target)
618                 .init(elementName, attrs);
619         } else {
620             new TaskHandler(helperImpl, parent, target, null, target)
621                 .init(elementName, attrs);
622         }
623     }
624
625     /**
626      * Handler for "description" elements.
627      */

628     static class DescriptionHandler extends AbstractHandler {
629
630         /**
631          * Constructor which just delegates to the superconstructor.
632          *
633          * @param parentHandler The handler which should be restored to the
634          * parser at the end of the element.
635          * Must not be <code>null</code>.
636          */

637         public DescriptionHandler(ProjectHelperImpl helperImpl,
638                                   DocumentHandler JavaDoc parentHandler) {
639             super(helperImpl, parentHandler);
640         }
641
642         /**
643          * Adds the text as description to the project.
644          *
645          * @param buf A character array of the text within the element.
646          * Will not be <code>null</code>.
647          * @param start The start element in the array.
648          * @param count The number of characters to read from the array.
649          */

650         public void characters(char[] buf, int start, int count) {
651             String JavaDoc text = new String JavaDoc(buf, start, count);
652             String JavaDoc currentDescription = helperImpl.project.getDescription();
653             if (currentDescription == null) {
654                 helperImpl.project.setDescription(text);
655             } else {
656                 helperImpl.project.setDescription(currentDescription + text);
657             }
658         }
659
660     }
661
662     /**
663      * Handler for all task elements.
664      */

665     static class TaskHandler extends AbstractHandler {
666         /** Containing target, if any. */
667         private Target target;
668         /**
669          * Container for the task, if any. If target is
670          * non-<code>null</code>, this must be too.
671          */

672         private TaskContainer container;
673         /**
674          * Task created by this handler.
675          */

676         private Task task;
677         /**
678          * Wrapper for the parent element, if any. The wrapper for this
679          * element will be added to this wrapper as a child.
680          */

681         private RuntimeConfigurable parentWrapper;
682         /**
683          * Wrapper for this element which takes care of actually configuring
684          * the element, if this element is contained within a target.
685          * Otherwise the configuration is performed with the configure method.
686          * @see ProjectHelper#configure(Object,AttributeList,Project)
687          */

688         private RuntimeConfigurable wrapper = null;
689
690         /**
691          * Constructor.
692          *
693          * @param parentHandler The handler which should be restored to the
694          * parser at the end of the element.
695          * Must not be <code>null</code>.
696          *
697          * @param container Container for the element.
698          * Must not be <code>null</code>.
699          *
700          * @param parentWrapper Wrapper for the parent element, if any.
701          * May be <code>null</code>.
702          *
703          * @param target Target this element is part of.
704          * Must not be <code>null</code>.
705          */

706         public TaskHandler(ProjectHelperImpl helperImpl, DocumentHandler JavaDoc parentHandler,
707                            TaskContainer container,
708                            RuntimeConfigurable parentWrapper, Target target) {
709             super(helperImpl, parentHandler);
710             this.container = container;
711             this.parentWrapper = parentWrapper;
712             this.target = target;
713         }
714
715         /**
716          * Initialisation routine called after handler creation
717          * with the element name and attributes. This configures
718          * the element with its attributes and sets it up with
719          * its parent container (if any). Nested elements are then
720          * added later as the parser encounters them.
721          *
722          * @param tag Name of the element which caused this handler
723          * to be created. Must not be <code>null</code>.
724          *
725          * @param attrs Attributes of the element which caused this
726          * handler to be created. Must not be <code>null</code>.
727          *
728          * @exception SAXParseException in case of error (not thrown in
729          * this implementation)
730          */

731         public void init(String JavaDoc tag, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
732             try {
733                 task = helperImpl.project.createTask(tag);
734             } catch (BuildException e) {
735                 // swallow here, will be thrown again in
736
// UnknownElement.maybeConfigure if the problem persists.
737
}
738
739             if (task == null) {
740                 task = new UnknownElement(tag);
741                 task.setProject(helperImpl.project);
742                 //XXX task.setTaskType(tag);
743
task.setTaskName(tag);
744             }
745
746             task.setLocation(new Location(helperImpl.locator));
747             helperImpl.configureId(task, attrs);
748
749             task.setOwningTarget(target);
750             container.addTask(task);
751             task.init();
752             wrapper = task.getRuntimeConfigurableWrapper();
753             wrapper.setAttributes(attrs);
754             if (parentWrapper != null) {
755                 parentWrapper.addChild(wrapper);
756             }
757         }
758
759         /**
760          * Adds text to the task, using the wrapper.
761          *
762          * @param buf A character array of the text within the element.
763          * Will not be <code>null</code>.
764          * @param start The start element in the array.
765          * @param count The number of characters to read from the array.
766          */

767         public void characters(char[] buf, int start, int count) {
768             wrapper.addText(buf, start, count);
769         }
770
771         /**
772          * Handles the start of an element within a target. Task containers
773          * will always use another task handler, and all other tasks
774          * will always use a nested element handler.
775          *
776          * @param name The name of the element being started.
777          * Will not be <code>null</code>.
778          * @param attrs Attributes of the element being started.
779          * Will not be <code>null</code>.
780          *
781          * @exception SAXParseException if an error occurs when initialising
782          * the appropriate child handler
783          */

784         public void startElement(String JavaDoc name, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
785             if (task instanceof TaskContainer) {
786                 // task can contain other tasks - no other nested elements possible
787
new TaskHandler(helperImpl, this, (TaskContainer) task,
788                     wrapper, target).init(name, attrs);
789             } else {
790                 new NestedElementHandler(helperImpl, this, task,
791                     wrapper, target).init(name, attrs);
792             }
793         }
794     }
795
796     /**
797      * Handler for all nested properties.
798      */

799     static class NestedElementHandler extends AbstractHandler {
800         /** Parent object (task/data type/etc). */
801         private Object JavaDoc parent;
802         /** The nested element itself. */
803         private Object JavaDoc child;
804         /**
805          * Wrapper for the parent element, if any. The wrapper for this
806          * element will be added to this wrapper as a child.
807          */

808         private RuntimeConfigurable parentWrapper;
809         /**
810          * Wrapper for this element which takes care of actually configuring
811          * the element, if a parent wrapper is provided.
812          * Otherwise the configuration is performed with the configure method.
813          * @see ProjectHelper#configure(Object,AttributeList,Project)
814          */

815         private RuntimeConfigurable childWrapper = null;
816         /** Target this element is part of, if any. */
817         private Target target;
818
819         /**
820          * Constructor.
821          *
822          * @param parentHandler The handler which should be restored to the
823          * parser at the end of the element.
824          * Must not be <code>null</code>.
825          *
826          * @param parent Parent of this element (task/data type/etc).
827          * Must not be <code>null</code>.
828          *
829          * @param parentWrapper Wrapper for the parent element, if any.
830          * Must not be <code>null</code>.
831          *
832          * @param target Target this element is part of.
833          * Must not be <code>null</code>.
834          */

835         public NestedElementHandler(ProjectHelperImpl helperImpl,
836                                     DocumentHandler JavaDoc parentHandler,
837                                     Object JavaDoc parent,
838                                     RuntimeConfigurable parentWrapper,
839                                     Target target) {
840             super(helperImpl, parentHandler);
841
842             if (parent instanceof TypeAdapter) {
843                 this.parent = ((TypeAdapter) parent).getProxy();
844             } else {
845                 this.parent = parent;
846             }
847             this.parentWrapper = parentWrapper;
848             this.target = target;
849         }
850
851         /**
852          * Initialisation routine called after handler creation
853          * with the element name and attributes. This configures
854          * the element with its attributes and sets it up with
855          * its parent container (if any). Nested elements are then
856          * added later as the parser encounters them.
857          *
858          * @param propType Name of the element which caused this handler
859          * to be created. Must not be <code>null</code>.
860          *
861          * @param attrs Attributes of the element which caused this
862          * handler to be created. Must not be <code>null</code>.
863          *
864          * @exception SAXParseException in case of error, such as a
865          * BuildException being thrown during configuration.
866          */

867         public void init(String JavaDoc propType, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
868             Class JavaDoc parentClass = parent.getClass();
869             IntrospectionHelper ih =
870                 IntrospectionHelper.getHelper(helperImpl.project, parentClass);
871
872             try {
873                 String JavaDoc elementName = propType.toLowerCase(Locale.US);
874                 if (parent instanceof UnknownElement) {
875                     UnknownElement uc = new UnknownElement(elementName);
876                     uc.setProject(helperImpl.project);
877                     ((UnknownElement) parent).addChild(uc);
878                     child = uc;
879                 } else {
880                     child = ih.createElement(helperImpl.project, parent, elementName);
881                 }
882
883                 helperImpl.configureId(child, attrs);
884
885                 childWrapper = new RuntimeConfigurable(child, propType);
886                 childWrapper.setAttributes(attrs);
887                 parentWrapper.addChild(childWrapper);
888             } catch (BuildException exc) {
889                 throw new SAXParseException JavaDoc(exc.getMessage(), helperImpl.locator, exc);
890             }
891         }
892
893         /**
894          * Adds text to the element, using the wrapper.
895          *
896          * @param buf A character array of the text within the element.
897          * Will not be <code>null</code>.
898          * @param start The start element in the array.
899          * @param count The number of characters to read from the array.
900          */

901         public void characters(char[] buf, int start, int count) {
902             childWrapper.addText(buf, start, count);
903         }
904
905         /**
906          * Handles the start of an element within this one. Task containers
907          * will always use a task handler, and all other elements
908          * will always use another nested element handler.
909          *
910          * @param name The name of the element being started.
911          * Will not be <code>null</code>.
912          * @param attrs Attributes of the element being started.
913          * Will not be <code>null</code>.
914          *
915          * @exception SAXParseException if an error occurs when initialising
916          * the appropriate child handler
917          */

918         public void startElement(String JavaDoc name, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
919             if (child instanceof TaskContainer) {
920                 // taskcontainer nested element can contain other tasks - no other
921
// nested elements possible
922
new TaskHandler(helperImpl, this, (TaskContainer) child,
923                     childWrapper, target).init(name, attrs);
924             } else {
925                 new NestedElementHandler(helperImpl, this, child,
926                     childWrapper, target).init(name, attrs);
927             }
928         }
929     }
930
931     /**
932      * Handler for all data types directly subordinate to project or target.
933      */

934     static class DataTypeHandler extends AbstractHandler {
935         /** Parent target, if any. */
936         private Target target;
937         /** The element being configured. */
938         private Object JavaDoc element;
939         /** Wrapper for this element, if it's part of a target. */
940         private RuntimeConfigurable wrapper = null;
941
942         /**
943          * Constructor with a target specified.
944          *
945          * @param parentHandler The handler which should be restored to the
946          * parser at the end of the element.
947          * Must not be <code>null</code>.
948          *
949          * @param target The parent target of this element.
950          * Must not be <code>null</code>.
951          */

952         public DataTypeHandler(ProjectHelperImpl helperImpl,
953                                DocumentHandler JavaDoc parentHandler, Target target) {
954             super(helperImpl, parentHandler);
955             this.target = target;
956         }
957
958         /**
959          * Initialisation routine called after handler creation
960          * with the element name and attributes. This configures
961          * the element with its attributes and sets it up with
962          * its parent container (if any). Nested elements are then
963          * added later as the parser encounters them.
964          *
965          * @param propType Name of the element which caused this handler
966          * to be created. Must not be <code>null</code>.
967          *
968          * @param attrs Attributes of the element which caused this
969          * handler to be created. Must not be <code>null</code>.
970          *
971          * @exception SAXParseException in case of error, such as a
972          * BuildException being thrown during configuration.
973          */

974         public void init(String JavaDoc propType, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
975             try {
976                 element = helperImpl.project.createDataType(propType);
977                 if (element == null) {
978                     throw new BuildException("Unknown data type " + propType);
979                 }
980
981                 wrapper = new RuntimeConfigurable(element, propType);
982                 wrapper.setAttributes(attrs);
983                 target.addDataType(wrapper);
984             } catch (BuildException exc) {
985                 throw new SAXParseException JavaDoc(exc.getMessage(), helperImpl.locator, exc);
986             }
987         }
988
989         /**
990          * Adds text to the using the wrapper.
991          *
992          * @param buf A character array of the text within the element.
993          * Will not be <code>null</code>.
994          * @param start The start element in the array.
995          * @param count The number of characters to read from the array.
996          *
997          * @see ProjectHelper#addText(Project,Object,char[],int,int)
998          */

999         public void characters(char[] buf, int start, int count) {
1000            wrapper.addText(buf, start, count);
1001        }
1002
1003        /**
1004         * Handles the start of an element within this one.
1005         * This will always use a nested element handler.
1006         *
1007         * @param name The name of the element being started.
1008         * Will not be <code>null</code>.
1009         * @param attrs Attributes of the element being started.
1010         * Will not be <code>null</code>.
1011         *
1012         * @exception SAXParseException if an error occurs when initialising
1013         * the child handler
1014         */

1015        public void startElement(String JavaDoc name, AttributeList JavaDoc attrs) throws SAXParseException JavaDoc {
1016            new NestedElementHandler(helperImpl, this, element, wrapper, target).init(name, attrs);
1017        }
1018    }
1019
1020    /**
1021     * Scans an attribute list for the <code>id</code> attribute and
1022     * stores a reference to the target object in the project if an
1023     * id is found.
1024     * <p>
1025     * This method was moved out of the configure method to allow
1026     * it to be executed at parse time.
1027     *
1028     * @see #configure(Object,AttributeList,Project)
1029     */

1030    private void configureId(Object JavaDoc target, AttributeList JavaDoc attr) {
1031        String JavaDoc id = attr.getValue("id");
1032        if (id != null) {
1033            project.addReference(id, target);
1034        }
1035    }
1036}
1037
Popular Tags