1 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 ; 29 30 import javax.xml.parsers.SAXParserFactory ; 31 import javax.xml.transform.OutputKeys ; 32 import javax.xml.transform.sax.SAXTransformerFactory ; 33 import javax.xml.transform.sax.TransformerHandler ; 34 import javax.xml.transform.stream.StreamResult ; 35 36 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 51 private XMLCatalog xmlCatalog = new XMLCatalog(); 52 private File lexiconFile = null; 53 private File grammarFile = null; 54 private String parserFactory = null; 55 private SAXParserFactory parserFactoryImpl = null; 56 private String transformerFactory = null; 57 private SAXTransformerFactory transformerFactoryImpl = null; 58 private String encoding = "ISO-8859-1"; 59 private boolean indent = false; 60 private boolean flatten = false; 61 private String 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 72 public ParserTask() {} 73 74 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 [] list = scanner.getIncludedFiles(); 108 109 for (int i = 0; i<list.length; i++) 110 { 111 String [] 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 127 public void setBasedir(File dir) 128 { 129 baseDir = dir; 130 } 131 132 137 public void setSrcdir(File dir) 138 { 139 srcDir = dir; 140 } 141 142 147 public void setDestdir(File dir) 148 { 149 destDir = dir; 150 } 151 152 155 public void setCachedir(File dir) 156 { 157 cacheDir = dir; 158 } 159 160 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 181 public void setLexicon(File lexiconFile) 182 { 183 this.lexiconFile = lexiconFile; 184 } 185 186 191 public void setGrammar(File grammarFile) 192 { 193 this.grammarFile = grammarFile; 194 } 195 196 201 public void setMsglevel(String 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 220 public void setEncoding(String encoding) 221 { 222 this.encoding = encoding; 223 } 224 225 230 public void setIndent(boolean indent) 231 { 232 this.indent = indent; 233 } 234 235 240 public void setFlatten(boolean flatten) 241 { 242 this.flatten = flatten; 243 } 244 245 250 public void setInputtype(String inputtype) 251 { 252 this.inputtype = inputtype; 253 } 254 255 260 public void setParser(String parserFactory) 261 { 262 this.parserFactory = parserFactory; 263 } 264 265 270 public void setTransformer(String transformerFactory) 271 { 272 this.transformerFactory = transformerFactory; 273 } 274 275 280 public void addConfiguredXMLCatalog(XMLCatalog xmlCatalog) 281 { 282 this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog); 283 } 284 285 288 public void init() throws BuildException 289 { 290 super.init(); 291 xmlCatalog.setProject(project); 292 } 293 294 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 format = new Properties (); 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 factory = getTransformerFactory(); 323 324 TransformerHandler serializer = factory.newTransformerHandler(); 325 serializer.getTransformer().setOutputProperties(format); 326 serializer.setResult(new StreamResult (outFile)); 327 328 if (this.parserautomaton!=null) { 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 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 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 String 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 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 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 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 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 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 line; 513 String newline = null; 514 String 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 551 { 552 SAXParserFactory 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 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 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 )Class.forName(parserFactory).newInstance(); 597 } 598 catch (Exception e) 599 { 600 throw new BuildException("Could not load parser factory", e); 601 } 602 } 603 604 return parserFactoryImpl; 605 } 606 607 private SAXTransformerFactory getTransformerFactory() 608 throws BuildException 609 { 610 if (transformerFactoryImpl==null) 611 { 612 try 613 { 614 if (transformerFactory==null) 615 transformerFactoryImpl = (SAXTransformerFactory )SAXTransformerFactory.newInstance(); 616 else 617 transformerFactoryImpl = 618 (SAXTransformerFactory )Class.forName(transformerFactory).newInstance(); 619 } 620 catch (Exception e) 621 { 622 throw new BuildException("Could not load transformer factory", e); 623 } 624 } 625 626 return transformerFactoryImpl; 627 } 628 } 629 | Popular Tags |