KickJava   Java API By Example, From Geeks To Geeks.

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


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.build.*;
12 import net.sourceforge.chaperon.model.grammar.*;
13 import net.sourceforge.chaperon.model.lexicon.*;
14 import net.sourceforge.chaperon.process.*;
15
16 import org.apache.tools.ant.*;
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.xml.sax.*;
24 import org.xml.sax.helpers.*;
25
26 import java.io.*;
27
28 import java.util.Properties JavaDoc;
29
30 import javax.xml.parsers.SAXParserFactory JavaDoc;
31 import javax.xml.transform.OutputKeys JavaDoc;
32 import javax.xml.transform.sax.SAXTransformerFactory JavaDoc;
33 import javax.xml.transform.sax.TransformerHandler JavaDoc;
34 import javax.xml.transform.stream.StreamResult JavaDoc;
35
36 /**
37  * A ant task for parsing text files
38  *
39  * @author <a HREF="mailto:stephan@apache.org">Stephan Michels </a>
40  * @version CVS $Id: ParserTask.java,v 1.2 2004/01/08 11:30:52 benedikta Exp $
41  */

42 public class ParserTask extends MatchingTask
43 {
44   private File srcDir = null;
45   private File destDir = null;
46   private File baseDir = null;
47   private File cacheDir = null;
48   private Mapper mapper = null;
49
50   /** for resolving entities such as dtds */
51   private XMLCatalog xmlCatalog = new XMLCatalog();
52   private File lexiconFile = null;
53   private File grammarFile = null;
54   private String JavaDoc parserFactory = null;
55   private SAXParserFactory JavaDoc parserFactoryImpl = null;
56   private String JavaDoc transformerFactory = null;
57   private SAXTransformerFactory JavaDoc transformerFactoryImpl = null;
58   private String JavaDoc encoding = "ISO-8859-1";
59   private boolean indent = false;
60   private boolean flatten = false;
61   private String JavaDoc inputtype = "text";
62   private int msgLevel = Project.MSG_ERR;
63   private AntLog log;
64   private ParserAutomaton parserautomaton = null;
65   private ParserProcessor parser = null;
66   private LexicalAutomaton lexicalautomaton = null;
67   private LexicalProcessor lexer = null;
68
69   /**
70    * Constructs the task
71    */

72   public ParserTask() {}
73
74   /**
75    * Executes the task
76    *
77    * @throws BuildException
78    */

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

127   public void setBasedir(File dir)
128   {
129     baseDir = dir;
130   }
131
132   /**
133    * Set the source directory
134    *
135    * @param dir Source directory
136    */

137   public void setSrcdir(File dir)
138   {
139     srcDir = dir;
140   }
141
142   /**
143    * Set the destination directory into which the result files should be copied to
144    *
145    * @param dir Destination directory
146    */

147   public void setDestdir(File dir)
148   {
149     destDir = dir;
150   }
151
152   /**
153    * @param dir Directory for chaching objects
154    */

155   public void setCachedir(File dir)
156   {
157     cacheDir = dir;
158   }
159
160   /**
161    * Creates a mapper.
162    *
163    * @return New mapper.
164    *
165    * @throws BuildException
166    */

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

181   public void setLexicon(File lexiconFile)
182   {
183     this.lexiconFile = lexiconFile;
184   }
185
186   /**
187    * Set the grammar, which should be used.
188    *
189    * @param grammarFile Grammar file.
190    */

191   public void setGrammar(File grammarFile)
192   {
193     this.grammarFile = grammarFile;
194   }
195
196   /**
197    * Sets the message level.
198    *
199    * @param msgLevel Message level.
200    */

201   public void setMsglevel(String JavaDoc msgLevel)
202   {
203     if (msgLevel.equalsIgnoreCase("debug"))
204       this.msgLevel = Project.MSG_DEBUG;
205     else if (msgLevel.equalsIgnoreCase("verbose"))
206       this.msgLevel = Project.MSG_VERBOSE;
207     else if (msgLevel.equalsIgnoreCase("info"))
208       this.msgLevel = Project.MSG_INFO;
209     else if (msgLevel.equalsIgnoreCase("warn"))
210       this.msgLevel = Project.MSG_WARN;
211     else if (msgLevel.equalsIgnoreCase("error"))
212       this.msgLevel = Project.MSG_ERR;
213   }
214
215   /**
216    * Sets the encoding for the input file
217    *
218    * @param encoding Encoding of the document
219    */

220   public void setEncoding(String JavaDoc encoding)
221   {
222     this.encoding = encoding;
223   }
224
225   /**
226    * Set if the output document should be indented
227    *
228    * @param indent If the output should be indented
229    */

230   public void setIndent(boolean indent)
231   {
232     this.indent = indent;
233   }
234
235   /**
236    * Reduces the deep of the produced hirachy by flatten nested element with same name.
237    *
238    * @param flatten If the hirache should be reduced.
239    */

240   public void setFlatten(boolean flatten)
241   {
242     this.flatten = flatten;
243   }
244
245   /**
246    * If the input document is a XML or a text document.
247    *
248    * @param inputtype Type of the input document.
249    */

250   public void setInputtype(String JavaDoc inputtype)
251   {
252     this.inputtype = inputtype;
253   }
254
255   /**
256    * Name of the parser factory.
257    *
258    * @param parserFactory Name of the parser factory.
259    */

260   public void setParser(String JavaDoc parserFactory)
261   {
262     this.parserFactory = parserFactory;
263   }
264
265   /**
266    * Name of the transformer factory.
267    *
268    * @param transformerFactory Name of the transformer factory.
269    */

270   public void setTransformer(String JavaDoc transformerFactory)
271   {
272     this.transformerFactory = transformerFactory;
273   }
274
275   /**
276    * Add the catalog to our internal catalog
277    *
278    * @param xmlCatalog the XMLCatalog instance to use to look up DTDs
279    */

280   public void addConfiguredXMLCatalog(XMLCatalog xmlCatalog)
281   {
282     this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog);
283   }
284
285   /**
286    * Initialize internal instance of XMLCatalog
287    */

288   public void init() throws BuildException
289   {
290     super.init();
291     xmlCatalog.setProject(project);
292   }
293
294   /**
295    * Processes the given input XML file and stores the result in the given resultFile.
296    *
297    * @param inFile The text file, which should parsed
298    * @param outFile The output file
299    *
300    * @throws BuildException
301    */

302   private void process(File inFile, File outFile) throws BuildException
303   {
304     try
305     {
306       if (!inFile.exists())
307         throw new BuildException("File "+inFile+" doesn't exists", location);
308
309       if (inFile.lastModified()>outFile.lastModified())
310       {
311         ensureDirectoryFor(outFile);
312         log("Parsing file "+inFile+" to "+outFile, Project.MSG_INFO);
313
314         Properties JavaDoc format = new Properties JavaDoc();
315
316         format.put(OutputKeys.ENCODING, encoding);
317         if (indent)
318           format.put(OutputKeys.INDENT, "yes");
319
320         format.put(OutputKeys.METHOD, "xml");
321
322         SAXTransformerFactory JavaDoc factory = getTransformerFactory();
323
324         TransformerHandler JavaDoc serializer = factory.newTransformerHandler();
325         serializer.getTransformer().setOutputProperties(format);
326         serializer.setResult(new StreamResult JavaDoc(outFile));
327
328         if (this.parserautomaton!=null) // && (this.parser==null))
329
{
330           this.parser = new ParserProcessor();
331           this.parser.setLog(log);
332           this.parser.setFlatten(this.flatten);
333           this.parser.setParserAutomaton(this.parserautomaton);
334           this.parser.setContentHandler(serializer);
335         }
336
337         this.lexer = new LexicalProcessor();
338         this.lexer.setLog(log);
339         this.lexer.setLexicalAutomaton(this.lexicalautomaton);
340         if (this.parserautomaton!=null)
341           this.lexer.setContentHandler(this.parser);
342         else
343           this.lexer.setContentHandler(serializer);
344
345         if (!inputtype.equalsIgnoreCase("xml"))
346           pushTextFile(inFile);
347         else
348           pushXMLFile(inFile);
349       }
350     }
351     catch (Exception JavaDoc ex)
352     {
353       if (outFile!=null)
354         outFile.delete();
355
356       if (ex instanceof BuildException)
357         throw (BuildException)ex;
358
359       throw new BuildException("Failed to process "+inFile+" : "+ex.getMessage(), ex);
360     }
361   }
362
363   /**
364    * Build the automata for the lexicon and grammar.
365    *
366    * @param lexiconFile Lexicon file.
367    * @param grammarFile Grammar file.
368    *
369    * @throws BuildException
370    */

371   private void buildAutomata(File lexiconFile, File grammarFile)
372     throws BuildException
373   {
374     if ((cacheDir!=null) && (!cacheDir.exists()))
375       throw new BuildException("Cache directory "+cacheDir+" doesn't exist");
376
377     try
378     {
379       // Lexicon
380
String JavaDoc filename = lexiconFile.getName();
381
382       File cacheFile = null;
383       if (cacheDir!=null)
384         cacheFile = new File(cacheDir, filename+".obj");
385
386       if ((cacheFile!=null) && (cacheFile.exists()) &&
387           (cacheFile.lastModified()>lexiconFile.lastModified()))
388       {
389         log("Reading lexicon from cache "+cacheFile, Project.MSG_DEBUG);
390
391         ObjectInputStream in = new ObjectInputStream(new FileInputStream(cacheFile));
392         this.lexicalautomaton = (LexicalAutomaton)in.readObject();
393         in.close();
394       }
395       else
396       {
397         log("Building lexicon from "+lexiconFile, Project.MSG_INFO);
398
399         SAXParserFactory JavaDoc factory = getParserFactory();
400
401         factory.setNamespaceAware(true);
402
403         XMLReader parser = factory.newSAXParser().getXMLReader();
404
405         parser.setEntityResolver(xmlCatalog);
406
407         LexiconFactory lexiconfactory = new LexiconFactory();
408         parser.setContentHandler(lexiconfactory);
409         try
410         {
411           parser.parse(lexiconFile.toString());
412         }
413         catch (SAXParseException se)
414         {
415           throw new BuildException("Couldn't parse file "+lexiconFile, se);
416         }
417
418         Lexicon lexicon = lexiconfactory.getLexicon();
419
420         this.lexicalautomaton = (new LexicalAutomatonBuilder(lexicon, log)).getLexicalAutomaton();
421
422         if (cacheFile!=null)
423         {
424           ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(cacheFile));
425           out.writeObject(this.lexicalautomaton);
426           out.flush();
427           out.close();
428         }
429       }
430
431       if (grammarFile!=null)
432       {
433         // Grammar
434
filename = grammarFile.getName();
435
436         cacheFile = null;
437         if (cacheDir!=null)
438           cacheFile = new File(cacheDir, filename+".obj");
439
440         if ((cacheFile!=null) && (cacheFile.exists()) &&
441             (cacheFile.lastModified()>grammarFile.lastModified()))
442         {
443           log("Reading grammar from cache "+cacheFile, Project.MSG_DEBUG);
444
445           ObjectInputStream in = new ObjectInputStream(new FileInputStream(cacheFile));
446           this.parserautomaton = (ParserAutomaton)in.readObject();
447           in.close();
448         }
449         else
450         {
451           log("Building grammar from "+grammarFile, Project.MSG_INFO);
452
453           SAXParserFactory JavaDoc factory = getParserFactory();
454
455           factory.setNamespaceAware(true);
456
457           XMLReader parser = factory.newSAXParser().getXMLReader();
458           parser.setEntityResolver(xmlCatalog);
459
460           GrammarFactory grammarfactory = new GrammarFactory();
461           parser.setContentHandler(grammarfactory);
462           try
463           {
464             parser.parse(grammarFile.toString());
465           }
466           catch (SAXParseException se)
467           {
468             throw new BuildException("Couldn't parse file "+lexiconFile, se);
469           }
470
471           Grammar grammar = grammarfactory.getGrammar();
472
473           this.parserautomaton = (new ParserAutomatonBuilder(grammar, log)).getParserAutomaton();
474
475           if (cacheFile!=null)
476           {
477             ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(cacheFile));
478             out.writeObject(this.parserautomaton);
479             out.flush();
480             out.close();
481           }
482         }
483       }
484     }
485     catch (Exception JavaDoc ex)
486     {
487       if (ex instanceof BuildException)
488         throw (BuildException)ex;
489
490       throw new BuildException(ex);
491     }
492   }
493
494   private void pushTextFile(File inFile) throws Exception JavaDoc
495   {
496     try
497     {
498       LocatorImpl locator = new LocatorImpl();
499
500       locator.setSystemId(inFile.toURL().toString());
501       locator.setLineNumber(1);
502       locator.setColumnNumber(1);
503
504       this.lexer.setDocumentLocator(locator);
505       this.lexer.startDocument();
506       this.lexer.startElement("http://chaperon.sourceforge.net/schema/text/1.0", "text", "text",
507                               new AttributesImpl());
508
509       LineNumberReader reader =
510         new LineNumberReader(new InputStreamReader(new FileInputStream(inFile)));
511
512       String JavaDoc line;
513       String JavaDoc newline = null;
514       String JavaDoc separator = System.getProperty("line.separator");
515
516       while (true)
517       {
518         if (newline==null)
519           line = reader.readLine();
520         else
521           line = newline;
522
523         if (line==null)
524           break;
525
526         newline = reader.readLine();
527
528         line = (newline!=null) ? (line+separator) : line;
529
530         locator.setLineNumber(reader.getLineNumber());
531         locator.setColumnNumber(1);
532         this.lexer.characters(line.toCharArray(), 0, line.length());
533
534         if (newline==null)
535           break;
536       }
537
538       reader.close();
539
540       this.lexer.endElement("http://chaperon.sourceforge.net/schema/text/1.0", "text", "text");
541       this.lexer.endDocument();
542     }
543     catch (SAXParseException se)
544     {
545       throw new BuildException("Exception occurs during parsing file "+inFile+" at line "+
546                                se.getLineNumber()+" column "+se.getColumnNumber(), se);
547     }
548   }
549
550   private void pushXMLFile(File inFile) throws Exception JavaDoc
551   {
552     SAXParserFactory JavaDoc parserfactory = getParserFactory();
553
554     parserfactory.setNamespaceAware(true);
555
556     XMLReader parser = parserfactory.newSAXParser().getXMLReader();
557
558     parser.setEntityResolver(xmlCatalog);
559
560     parser.setContentHandler(this.lexer);
561     try
562     {
563       parser.parse(inFile.toString());
564     }
565     catch (SAXParseException se)
566     {
567       throw new BuildException("Exception occurs during parsing file "+inFile+" at line "+
568                                se.getLineNumber()+" column "+se.getColumnNumber(), se);
569     }
570   }
571
572   /**
573    * Ensures the directory for the output
574    *
575    * @param targetFile The directory
576    *
577    * @throws BuildException
578    */

579   private void ensureDirectoryFor(File targetFile) throws BuildException
580   {
581     File directory = new File(targetFile.getParent());
582
583     if ((!directory.exists()) && (!directory.mkdirs()))
584       throw new BuildException("Unable to create directory: "+directory.getAbsolutePath());
585   }
586
587   private SAXParserFactory JavaDoc getParserFactory() throws BuildException
588   {
589     if (parserFactoryImpl==null)
590     {
591       try
592       {
593         if (parserFactory==null)
594           parserFactoryImpl = SAXParserFactory.newInstance();
595         else
596           parserFactoryImpl = (SAXParserFactory JavaDoc)Class.forName(parserFactory).newInstance();
597       }
598       catch (Exception JavaDoc e)
599       {
600         throw new BuildException("Could not load parser factory", e);
601       }
602     }
603
604     return parserFactoryImpl;
605   }
606
607   private SAXTransformerFactory JavaDoc getTransformerFactory()
608     throws BuildException
609   {
610     if (transformerFactoryImpl==null)
611     {
612       try
613       {
614         if (transformerFactory==null)
615           transformerFactoryImpl = (SAXTransformerFactory JavaDoc)SAXTransformerFactory.newInstance();
616         else
617           transformerFactoryImpl =
618             (SAXTransformerFactory JavaDoc)Class.forName(transformerFactory).newInstance();
619       }
620       catch (Exception JavaDoc e)
621       {
622         throw new BuildException("Could not load transformer factory", e);
623       }
624     }
625
626     return transformerFactoryImpl;
627   }
628 }
629
Popular Tags