KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > chaperon > ant > ExtendedParserTask


1 /*
2  * Copyright (C) Chaperon. All rights reserved.
3  * -------------------------------------------------------------------------
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE file.
7  */

8
9 package net.sourceforge.chaperon.ant;
10
11 import net.sourceforge.chaperon.model.extended.ExtendedGrammar;
12 import net.sourceforge.chaperon.process.extended.ExtendedDirectParserProcessor;
13
14 import org.apache.tools.ant.BuildException;
15 import org.apache.tools.ant.DirectoryScanner;
16 import org.apache.tools.ant.Project;
17 import org.apache.tools.ant.taskdefs.MatchingTask;
18 import org.apache.tools.ant.types.Mapper;
19 import org.apache.tools.ant.types.XMLCatalog;
20 import org.apache.tools.ant.util.FileNameMapper;
21 import org.apache.tools.ant.util.IdentityMapper;
22
23 import org.exolab.castor.mapping.Mapping;
24 import org.exolab.castor.xml.Unmarshaller;
25
26 import org.xml.sax.InputSource JavaDoc;
27 import org.xml.sax.SAXParseException JavaDoc;
28 import org.xml.sax.XMLReader JavaDoc;
29 import org.xml.sax.helpers.AttributesImpl JavaDoc;
30 import org.xml.sax.helpers.LocatorImpl JavaDoc;
31
32 import java.io.File JavaDoc;
33 import java.io.FileInputStream JavaDoc;
34 import java.io.FileReader JavaDoc;
35 import java.io.InputStreamReader JavaDoc;
36 import java.io.LineNumberReader JavaDoc;
37
38 import java.util.Properties JavaDoc;
39
40 import javax.xml.parsers.SAXParserFactory JavaDoc;
41 import javax.xml.transform.OutputKeys JavaDoc;
42 import javax.xml.transform.sax.SAXTransformerFactory JavaDoc;
43 import javax.xml.transform.sax.TransformerHandler JavaDoc;
44 import javax.xml.transform.stream.StreamResult JavaDoc;
45
46 /**
47  * A ant task for parsing text files
48  *
49  * @author <a HREF="mailto:stephan@apache.org">Stephan Michels </a>
50  * @version CVS $Id: ExtendedParserTask.java,v 1.3 2004/01/09 10:48:06 benedikta Exp $
51  */

52 public class ExtendedParserTask extends MatchingTask
53 {
54   private File JavaDoc srcDir = null;
55   private File JavaDoc destDir = null;
56   private File JavaDoc baseDir = null;
57   private Mapper mapper = null;
58
59   /** for resolving entities such as dtds */
60   private XMLCatalog xmlCatalog = new XMLCatalog();
61   private File JavaDoc grammarFile = null;
62   private String JavaDoc parserFactory = null;
63   private SAXParserFactory JavaDoc parserFactoryImpl = null;
64   private String JavaDoc transformerFactory = null;
65   private SAXTransformerFactory JavaDoc transformerFactoryImpl = null;
66   private String JavaDoc encoding = "ISO-8859-1";
67   private boolean indent = false;
68   private boolean flatten = false;
69   private String JavaDoc inputtype = "text";
70   private int msgLevel = Project.MSG_ERR;
71   private AntLog log;
72   private ExtendedGrammar grammar = null;
73   private ExtendedDirectParserProcessor parser = null;
74
75   /**
76    * Constructs the task
77    */

78   public ExtendedParserTask() {}
79
80   /**
81    * Executes the task
82    *
83    * @throws BuildException
84    */

85   public void execute() throws BuildException
86   {
87     if (baseDir==null)
88       baseDir = project.resolveFile(".");
89
90     if (grammarFile==null)
91       throw new BuildException("No grammar file is specified", location);
92
93     if (!grammarFile.exists())
94       throw new BuildException("Grammar file doesn't exists:"+grammarFile.getAbsolutePath(),
95                                location);
96
97     if (destDir==null)
98       throw new BuildException("No destdir specified!", location);
99
100     log = new AntLog(getProject(), msgLevel);
101
102     buildAutomata(grammarFile);
103
104     DirectoryScanner scanner = getDirectoryScanner(srcDir);
105
106     FileNameMapper mapperImpl;
107
108     if (mapper==null)
109       mapperImpl = new IdentityMapper();
110     else
111       mapperImpl = mapper.getImplementation();
112
113     String JavaDoc[] list = scanner.getIncludedFiles();
114
115     for (int i = 0; i<list.length; i++)
116     {
117       String JavaDoc[] dest = mapperImpl.mapFileName(list[i]);
118
119       if (dest!=null)
120         for (int j = 0; j<dest.length; j++)
121         {
122           log("Transforming "+list[i]+" to "+dest[j], Project.MSG_DEBUG);
123           process(new File JavaDoc(srcDir, list[i]), new File JavaDoc(destDir, dest[j]));
124         }
125     }
126   }
127
128   /**
129    * Set the base directory.
130    *
131    * @param dir Base directory
132    */

133   public void setBasedir(File JavaDoc dir)
134   {
135     baseDir = dir;
136   }
137
138   /**
139    * Set the source directory
140    *
141    * @param dir Source directory
142    */

143   public void setSrcdir(File JavaDoc dir)
144   {
145     srcDir = dir;
146   }
147
148   /**
149    * Set the destination directory into which the result files should be copied to
150    *
151    * @param dir Destination directory
152    */

153   public void setDestdir(File JavaDoc dir)
154   {
155     destDir = dir;
156   }
157
158   /**
159    * Creates a mapper.
160    *
161    * @return New mapper.
162    *
163    * @throws BuildException
164    */

165   public Mapper createMapper() throws BuildException
166   {
167     if (mapper!=null)
168       throw new BuildException("Cannot define more than one mapper", location);
169
170     mapper = new Mapper(project);
171     return mapper;
172   }
173
174   /**
175    * Set the grammar, which should be used.
176    *
177    * @param grammarFile Grammar file.
178    */

179   public void setGrammar(File JavaDoc grammarFile)
180   {
181     this.grammarFile = grammarFile;
182   }
183
184   /**
185    * Sets the message level.
186    *
187    * @param msgLevel Message level.
188    */

189   public void setMsglevel(String JavaDoc msgLevel)
190   {
191     if (msgLevel.equalsIgnoreCase("debug"))
192       this.msgLevel = Project.MSG_DEBUG;
193     else if (msgLevel.equalsIgnoreCase("verbose"))
194       this.msgLevel = Project.MSG_VERBOSE;
195     else if (msgLevel.equalsIgnoreCase("info"))
196       this.msgLevel = Project.MSG_INFO;
197     else if (msgLevel.equalsIgnoreCase("warn"))
198       this.msgLevel = Project.MSG_WARN;
199     else if (msgLevel.equalsIgnoreCase("error"))
200       this.msgLevel = Project.MSG_ERR;
201   }
202
203   /**
204    * Sets the encoding for the input file
205    *
206    * @param encoding Encoding of the document
207    */

208   public void setEncoding(String JavaDoc encoding)
209   {
210     this.encoding = encoding;
211   }
212
213   /**
214    * Set if the output document should be indented
215    *
216    * @param indent If the output should be indented
217    */

218   public void setIndent(boolean indent)
219   {
220     this.indent = indent;
221   }
222
223   /**
224    * If the input document is a XML or a text document.
225    *
226    * @param inputtype Type of the input document.
227    */

228   public void setInputtype(String JavaDoc inputtype)
229   {
230     this.inputtype = inputtype;
231   }
232
233   /**
234    * Name of the parser factory.
235    *
236    * @param parserFactory Name of the parser factory.
237    */

238   public void setParser(String JavaDoc parserFactory)
239   {
240     this.parserFactory = parserFactory;
241   }
242
243   /**
244    * Name of the transformer factory.
245    *
246    * @param transformerFactory Name of the transformer factory.
247    */

248   public void setTransformer(String JavaDoc transformerFactory)
249   {
250     this.transformerFactory = transformerFactory;
251   }
252
253   /**
254    * Add the catalog to our internal catalog
255    *
256    * @param xmlCatalog the XMLCatalog instance to use to look up DTDs
257    */

258   public void addConfiguredXMLCatalog(XMLCatalog xmlCatalog)
259   {
260     this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog);
261   }
262
263   /**
264    * Initialize internal instance of XMLCatalog
265    */

266   public void init() throws BuildException
267   {
268     super.init();
269     xmlCatalog.setProject(project);
270   }
271
272   /**
273    * Processes the given input XML file and stores the result in the given resultFile.
274    *
275    * @param inFile The text file, which should parsed
276    * @param outFile The output file
277    *
278    * @throws BuildException
279    */

280   private void process(File JavaDoc inFile, File JavaDoc outFile) throws BuildException
281   {
282     try
283     {
284       if (!inFile.exists())
285         throw new BuildException("File "+inFile+" doesn't exists", location);
286
287       if (inFile.lastModified()>outFile.lastModified())
288       {
289         ensureDirectoryFor(outFile);
290         log("Parsing file "+inFile+" to "+outFile, Project.MSG_INFO);
291
292         Properties JavaDoc format = new Properties JavaDoc();
293
294         format.put(OutputKeys.ENCODING, encoding);
295         if (indent)
296           format.put(OutputKeys.INDENT, "yes");
297
298         format.put(OutputKeys.METHOD, "xml");
299
300         SAXTransformerFactory JavaDoc factory = getTransformerFactory();
301
302         TransformerHandler JavaDoc serializer = factory.newTransformerHandler();
303         serializer.getTransformer().setOutputProperties(format);
304         serializer.setResult(new StreamResult JavaDoc(outFile));
305
306         this.parser = new ExtendedDirectParserProcessor();
307         this.parser.setLog(log);
308         this.parser.setFlatten(this.flatten);
309
310         this.parser.setExtendedGrammar(this.grammar);
311         this.parser.setContentHandler(serializer);
312
313         if (!inputtype.equalsIgnoreCase("xml"))
314           pushTextFile(inFile);
315         else
316           pushXMLFile(inFile);
317       }
318     }
319     catch (Exception JavaDoc ex)
320     {
321       if (outFile!=null)
322         outFile.delete();
323
324       if (ex instanceof BuildException)
325         throw (BuildException)ex;
326
327       throw new BuildException("Failed to process "+inFile+" : "+ex.getMessage(), ex);
328     }
329   }
330
331   /**
332    * Build the automata for the lexicon and grammar.
333    *
334    * @param grammarFile Grammar file.
335    *
336    * @throws BuildException
337    */

338   private void buildAutomata(File JavaDoc grammarFile) throws BuildException
339   {
340     try
341     {
342       log("Building grammar from "+grammarFile, Project.MSG_INFO);
343
344       SAXParserFactory JavaDoc factory = getParserFactory();
345
346       factory.setNamespaceAware(true);
347
348       XMLReader JavaDoc parser = factory.newSAXParser().getXMLReader();
349       parser.setEntityResolver(xmlCatalog);
350
351       Mapping mapping = new Mapping();
352       mapping.loadMapping(new InputSource JavaDoc(ExtendedGrammar.class.getResource("mapping.xml")
353                                                                .openStream()));
354
355       Unmarshaller unmarshaller = new Unmarshaller(ExtendedGrammar.class);
356       unmarshaller.setMapping(mapping);
357
358       this.grammar = (ExtendedGrammar)unmarshaller.unmarshal(new FileReader JavaDoc(grammarFile));
359
360       if (log.isDebugEnabled())
361         log.debug("grammar:\n"+grammar);
362     }
363     catch (Exception JavaDoc ex)
364     {
365       if (ex instanceof BuildException)
366         throw (BuildException)ex;
367
368       throw new BuildException(ex);
369     }
370   }
371
372   private void pushTextFile(File JavaDoc inFile) throws Exception JavaDoc
373   {
374     try
375     {
376       LocatorImpl JavaDoc locator = new LocatorImpl JavaDoc();
377
378       locator.setSystemId(inFile.toURL().toString());
379       locator.setLineNumber(1);
380       locator.setColumnNumber(1);
381
382       this.parser.setDocumentLocator(locator);
383       this.parser.startDocument();
384       this.parser.startElement("http://chaperon.sourceforge.net/schema/text/1.0", "text", "text",
385                                new AttributesImpl JavaDoc());
386
387       LineNumberReader JavaDoc reader =
388         new LineNumberReader JavaDoc(new InputStreamReader JavaDoc(new FileInputStream JavaDoc(inFile)));
389
390       String JavaDoc line;
391       String JavaDoc newline = null;
392       String JavaDoc separator = System.getProperty("line.separator");
393
394       while (true)
395       {
396         if (newline==null)
397           line = reader.readLine();
398         else
399           line = newline;
400
401         if (line==null)
402           break;
403
404         newline = reader.readLine();
405
406         line = (newline!=null) ? (line+separator) : line;
407
408         locator.setLineNumber(reader.getLineNumber());
409         locator.setColumnNumber(1);
410         this.parser.characters(line.toCharArray(), 0, line.length());
411
412         if (newline==null)
413           break;
414       }
415
416       reader.close();
417
418       this.parser.endElement("http://chaperon.sourceforge.net/schema/text/1.0", "text", "text");
419       this.parser.endDocument();
420     }
421     catch (SAXParseException JavaDoc se)
422     {
423       throw new BuildException("Exception occurs during parsing file "+inFile+" at line "+
424                                se.getLineNumber()+" column "+se.getColumnNumber(), se);
425     }
426   }
427
428   private void pushXMLFile(File JavaDoc inFile) throws Exception JavaDoc
429   {
430     SAXParserFactory JavaDoc parserfactory = getParserFactory();
431
432     parserfactory.setNamespaceAware(true);
433
434     XMLReader JavaDoc parser = parserfactory.newSAXParser().getXMLReader();
435
436     parser.setEntityResolver(xmlCatalog);
437
438     parser.setContentHandler(this.parser);
439     try
440     {
441       parser.parse(inFile.toString());
442     }
443     catch (SAXParseException JavaDoc se)
444     {
445       throw new BuildException("Exception occurs during parsing file "+inFile+" at line "+
446                                se.getLineNumber()+" column "+se.getColumnNumber(), se);
447     }
448   }
449
450   /**
451    * Ensures the directory for the output
452    *
453    * @param targetFile The directory
454    *
455    * @throws BuildException
456    */

457   private void ensureDirectoryFor(File JavaDoc targetFile) throws BuildException
458   {
459     File JavaDoc directory = new File JavaDoc(targetFile.getParent());
460
461     if ((!directory.exists()) && (!directory.mkdirs()))
462       throw new BuildException("Unable to create directory: "+directory.getAbsolutePath());
463   }
464
465   private SAXParserFactory JavaDoc getParserFactory() throws BuildException
466   {
467     if (parserFactoryImpl==null)
468     {
469       try
470       {
471         if (parserFactory==null)
472           parserFactoryImpl = SAXParserFactory.newInstance();
473         else
474           parserFactoryImpl = (SAXParserFactory JavaDoc)Class.forName(parserFactory).newInstance();
475       }
476       catch (Exception JavaDoc e)
477       {
478         throw new BuildException("Could not load parser factory", e);
479       }
480     }
481
482     return parserFactoryImpl;
483   }
484
485   private SAXTransformerFactory JavaDoc getTransformerFactory()
486     throws BuildException
487   {
488     if (transformerFactoryImpl==null)
489     {
490       try
491       {
492         if (transformerFactory==null)
493           transformerFactoryImpl = (SAXTransformerFactory JavaDoc)SAXTransformerFactory.newInstance();
494         else
495           transformerFactoryImpl =
496             (SAXTransformerFactory JavaDoc)Class.forName(transformerFactory).newInstance();
497       }
498       catch (Exception JavaDoc e)
499       {
500         throw new BuildException("Could not load transformer factory", e);
501       }
502     }
503
504     return transformerFactoryImpl;
505   }
506 }
507
Popular Tags