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 = <