1 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 ; 27 import org.xml.sax.SAXParseException ; 28 import org.xml.sax.XMLReader ; 29 import org.xml.sax.helpers.AttributesImpl ; 30 import org.xml.sax.helpers.LocatorImpl ; 31 32 import java.io.File ; 33 import java.io.FileInputStream ; 34 import java.io.FileReader ; 35 import java.io.InputStreamReader ; 36 import java.io.LineNumberReader ; 37 38 import java.util.Properties ; 39 40 import javax.xml.parsers.SAXParserFactory ; 41 import javax.xml.transform.OutputKeys ; 42 import javax.xml.transform.sax.SAXTransformerFactory ; 43 import javax.xml.transform.sax.TransformerHandler ; 44 import javax.xml.transform.stream.StreamResult ; 45 46 52 public class ExtendedParserTask extends MatchingTask 53 { 54 private File srcDir = null; 55 private File destDir = null; 56 private File baseDir = null; 57 private Mapper mapper = null; 58 59 60 private XMLCatalog xmlCatalog = new XMLCatalog(); 61 private File grammarFile = null; 62 private String parserFactory = null; 63 private SAXParserFactory parserFactoryImpl = null; 64 private String transformerFactory = null; 65 private SAXTransformerFactory transformerFactoryImpl = null; 66 private String encoding = "ISO-8859-1"; 67 private boolean indent = false; 68 private boolean flatten = false; 69 private String 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 78 public ExtendedParserTask() {} 79 80 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 [] list = scanner.getIncludedFiles(); 114 115 for (int i = 0; i<list.length; i++) 116 { 117 String [] 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 (srcDir, list[i]), new File (destDir, dest[j])); 124 } 125 } 126 } 127 128 133 public void setBasedir(File dir) 134 { 135 baseDir = dir; 136 } 137 138 143 public void setSrcdir(File dir) 144 { 145 srcDir = dir; 146 } 147 148 153 public void setDestdir(File dir) 154 { 155 destDir = dir; 156 } 157 158 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 179 public void setGrammar(File grammarFile) 180 { 181 this.grammarFile = grammarFile; 182 } 183 184 189 public void setMsglevel(String 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 208 public void setEncoding(String encoding) 209 { 210 this.encoding = encoding; 211 } 212 213 218 public void setIndent(boolean indent) 219 { 220 this.indent = indent; 221 } 222 223 228 public void setInputtype(String inputtype) 229 { 230 this.inputtype = inputtype; 231 } 232 233 238 public void setParser(String parserFactory) 239 { 240 this.parserFactory = parserFactory; 241 } 242 243 248 public void setTransformer(String transformerFactory) 249 { 250 this.transformerFactory = transformerFactory; 251 } 252 253 258 public void addConfiguredXMLCatalog(XMLCatalog xmlCatalog) 259 { 260 this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog); 261 } 262 263 266 public void init() throws BuildException 267 { 268 super.init(); 269 xmlCatalog.setProject(project); 270 } 271 272 280 private void process(File inFile, File 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 format = new Properties (); 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 factory = getTransformerFactory(); 301 302 TransformerHandler serializer = factory.newTransformerHandler(); 303 serializer.getTransformer().setOutputProperties(format); 304 serializer.setResult(new StreamResult (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 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 338 private void buildAutomata(File grammarFile) throws BuildException 339 { 340 try 341 { 342 log("Building grammar from "+grammarFile, Project.MSG_INFO); 343 344 SAXParserFactory factory = getParserFactory(); 345 346 factory.setNamespaceAware(true); 347 348 XMLReader parser = factory.newSAXParser().getXMLReader(); 349 parser.setEntityResolver(xmlCatalog); 350 351 Mapping mapping = new Mapping(); 352 mapping.loadMapping(new InputSource (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 (grammarFile)); 359 360 if (log.isDebugEnabled()) 361 log.debug("grammar:\n"+grammar); 362 } 363 catch (Exception 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 inFile) throws Exception 373 { 374 try 375 { 376 LocatorImpl locator = new LocatorImpl (); 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 ()); 386 387 LineNumberReader reader = 388 new LineNumberReader (new InputStreamReader (new FileInputStream (inFile))); 389 390 String line; 391 String newline = null; 392 String 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 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 inFile) throws Exception 429 { 430 SAXParserFactory parserfactory = getParserFactory(); 431 432 parserfactory.setNamespaceAware(true); 433 434 XMLReader 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 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 457 private void ensureDirectoryFor(File targetFile) throws BuildException 458 { 459 File directory = new File (targetFile.getParent()); 460 461 if ((!directory.exists()) && (!directory.mkdirs())) 462 throw new BuildException("Unable to create directory: "+directory.getAbsolutePath()); 463 } 464 465 private SAXParserFactory 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 )Class.forName(parserFactory).newInstance(); 475 } 476 catch (Exception e) 477 { 478 throw new BuildException("Could not load parser factory", e); 479 } 480 } 481 482 return parserFactoryImpl; 483 } 484 485 private SAXTransformerFactory getTransformerFactory() 486 throws BuildException 487 { 488 if (transformerFactoryImpl==null) 489 { 490 try 491 { 492 if (transformerFactory==null) 493 transformerFactoryImpl = (SAXTransformerFactory )SAXTransformerFactory.newInstance(); 494 else 495 transformerFactoryImpl = 496 (SAXTransformerFactory )Class.forName(transformerFactory).newInstance(); 497 } 498 catch (Exception e) 499 { 500 throw new BuildException("Could not load transformer factory", e); 501 } 502 } 503 504 return transformerFactoryImpl; 505 } 506 } 507 | Popular Tags |