1 52 53 package freemarker.ext.ant; 54 55 import java.io.*; 56 import java.util.*; 57 58 import org.w3c.dom.*; 59 import org.xml.sax.SAXParseException ; 60 import javax.xml.parsers.DocumentBuilder ; 61 import javax.xml.parsers.DocumentBuilderFactory ; 62 import javax.xml.parsers.ParserConfigurationException ; 63 64 import org.apache.tools.ant.BuildException; 65 import org.apache.tools.ant.DirectoryScanner; 66 import org.apache.tools.ant.Project; 67 import org.apache.tools.ant.taskdefs.MatchingTask; 68 import freemarker.ext.xml.NodeListModel; 69 import freemarker.ext.dom.NodeModel; 70 import freemarker.template.utility.ClassUtil; 71 import freemarker.template.utility.SecurityUtilities; 72 import freemarker.template.*; 73 74 75 252 public class FreemarkerXmlTask 253 extends 254 MatchingTask 255 { 256 private JythonAntTask prepareModel; 257 private JythonAntTask prepareEnvironment; 258 private final DocumentBuilderFactory builderFactory; 259 private DocumentBuilder builder; 260 261 262 private Configuration cfg = new Configuration(); 263 264 265 private File destDir; 266 267 268 private File baseDir; 269 270 272 private File templateDir; 273 274 275 private String templateName; 276 277 278 private Template parsedTemplate; 279 280 281 private long templateFileLastModified = 0; 282 283 284 private String projectAttribute = null; 285 286 private File projectFile = null; 287 288 289 private TemplateModel projectTemplate; 290 private TemplateNodeModel projectNode; 292 private TemplateModel propertiesTemplate; 293 private TemplateModel userPropertiesTemplate; 294 295 296 private long projectFileLastModified = 0; 297 298 299 private boolean incremental = true; 300 301 302 private String extension = ".html"; 303 304 private String encoding = SecurityUtilities.getSystemProperty("file.encoding"); 305 private String templateEncoding = encoding; 306 private boolean validation = false; 307 308 private String models = ""; 309 private final Map modelsMap = new HashMap(); 310 311 312 313 316 public FreemarkerXmlTask() 317 { 318 builderFactory = DocumentBuilderFactory.newInstance(); 319 builderFactory.setNamespaceAware(true); 320 } 321 322 325 public void setBasedir(File dir) 326 { 327 baseDir = dir; 328 } 329 330 335 public void setDestdir(File dir) 336 { 337 destDir = dir; 338 } 339 340 343 public void setExtension(String extension) 344 { 345 this.extension = extension; 346 } 347 348 public void setTemplate(String templateName) { 349 this.templateName = templateName; 350 } 351 352 public void setTemplateDir(File templateDir) throws BuildException { 353 this.templateDir = templateDir; 354 try { 355 cfg.setDirectoryForTemplateLoading(templateDir); 356 } catch (Exception e) { 357 throw new BuildException(e); 358 } 359 } 360 361 364 public void setProjectfile(String projectAttribute) 365 { 366 this.projectAttribute = projectAttribute; 367 } 368 369 372 public void setIncremental(String incremental) 373 { 374 this.incremental = !(incremental.equalsIgnoreCase("false") || incremental.equalsIgnoreCase("no") || incremental.equalsIgnoreCase("off")); 375 } 376 377 380 public void setEncoding(String encoding) 381 { 382 this.encoding = encoding; 383 } 384 385 public void setTemplateEncoding(String inputEncoding) 386 { 387 this.templateEncoding = inputEncoding; 388 } 389 390 393 public void setValidation(boolean validation) 394 { 395 this.validation = validation; 396 } 397 398 public void setModels(String models) 399 { 400 this.models = models; 401 } 402 403 public void execute() throws BuildException 404 { 405 DirectoryScanner scanner; 406 String [] list; 407 408 if (baseDir == null) 409 { 410 baseDir = getProject().getBaseDir(); 411 } 412 if (destDir == null ) 413 { 414 String msg = "destdir attribute must be set!"; 415 throw new BuildException(msg, getLocation()); 416 } 417 418 File templateFile = null; 419 420 if (templateDir == null) { 421 if (templateName != null) { 422 templateFile = new File(templateName); 423 if (!templateFile.isAbsolute()) { 424 templateFile = new File(getProject().getBaseDir(), templateName); 425 } 426 templateDir = templateFile.getParentFile(); 427 templateName = templateFile.getName(); 428 } 429 else { 430 templateDir = baseDir; 431 } 432 setTemplateDir(templateDir); 433 } else if (templateName != null) { 434 if (new File(templateName).isAbsolute()) { 435 throw new BuildException("Do not specify an absolute location for the template as well as a templateDir"); 436 } 437 templateFile = new File(templateDir, templateName); 438 } 439 if (templateFile != null) { 440 templateFileLastModified = templateFile.lastModified(); 441 } 442 443 try { 444 if (templateName != null) { 445 parsedTemplate = cfg.getTemplate(templateName, templateEncoding); 446 } 447 } 448 catch (IOException ioe) { 449 throw new BuildException(ioe.toString()); 450 } 451 log("Transforming into: " + destDir.getAbsolutePath(), Project.MSG_INFO); 453 454 if (projectAttribute != null && projectAttribute.length() > 0) 456 { 457 projectFile = new File(baseDir, projectAttribute); 458 if (projectFile.isFile()) 459 projectFileLastModified = projectFile.lastModified(); 460 else 461 { 462 log ("Project file is defined, but could not be located: " + 463 projectFile.getAbsolutePath(), Project.MSG_INFO ); 464 projectFile = null; 465 } 466 } 467 468 generateModels(); 469 470 scanner = getDirectoryScanner(baseDir); 472 473 propertiesTemplate = wrapMap(project.getProperties()); 474 userPropertiesTemplate = wrapMap(project.getUserProperties()); 475 476 builderFactory.setValidating(validation); 477 try 478 { 479 builder = builderFactory.newDocumentBuilder(); 480 } 481 catch(ParserConfigurationException e) 482 { 483 throw new BuildException("Could not create document builder", e, getLocation()); 484 } 485 486 list = scanner.getIncludedFiles(); 488 489 490 for (int i = 0;i < list.length; ++i) 491 { 492 process(baseDir, list[i], destDir); 493 } 494 } 495 496 public void addConfiguredJython(JythonAntTask jythonAntTask) { 497 this.prepareEnvironment = jythonAntTask; 498 } 499 500 public void addConfiguredPrepareModel(JythonAntTask prepareModel) { 501 this.prepareModel = prepareModel; 502 } 503 504 public void addConfiguredPrepareEnvironment(JythonAntTask prepareEnvironment) { 505 this.prepareEnvironment = prepareEnvironment; 506 } 507 508 511 private void process(File baseDir, String xmlFile, File destDir) 512 throws BuildException 513 { 514 File outFile=null; 515 File inFile=null; 516 try 517 { 518 inFile = new File(baseDir,xmlFile); 520 outFile = new File(destDir, 522 xmlFile.substring(0, 523 xmlFile.lastIndexOf('.')) + extension); 524 525 if (!incremental || 527 (inFile.lastModified() > outFile.lastModified() || 528 templateFileLastModified > outFile.lastModified() || 529 projectFileLastModified > outFile.lastModified())) 530 { 531 ensureDirectoryFor(outFile); 532 533 log("Input: " + xmlFile, Project.MSG_INFO ); 535 536 if (projectTemplate == null && projectFile != null) { 537 Document doc = builder.parse(projectFile); 538 projectTemplate = new NodeListModel(builder.parse(projectFile)); 539 projectNode = NodeModel.wrap(doc); 540 } 541 542 Document docNode = builder.parse(inFile); 544 545 TemplateModel document = new NodeListModel(docNode); 546 TemplateNodeModel docNodeModel = NodeModel.wrap(docNode); 547 HashMap root = new HashMap(); 548 root.put("document", document); 549 insertDefaults(root); 550 551 Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), encoding)); 554 try 555 { 556 if (parsedTemplate == null) { 557 throw new BuildException("No template file specified in build script or in XML file"); 558 } 559 if (prepareModel != null) { 560 Map vars = new HashMap(); 561 vars.put("model", root); 562 vars.put("doc", docNode); 563 if (projectNode != null) { 564 vars.put("project", ((NodeModel) projectNode).getNode()); 565 } 566 prepareModel.execute(vars); 567 } 568 freemarker.core.Environment env = parsedTemplate.createProcessingEnvironment(root, writer); 569 env.setCurrentVisitorNode(docNodeModel); 570 if (prepareEnvironment != null) { 571 Map vars = new HashMap(); 572 vars.put("env", env); 573 vars.put("doc", docNode); 574 if (projectNode != null) { 575 vars.put("project", ((NodeModel) projectNode).getNode()); 576 } 577 prepareEnvironment.execute(vars); 578 } 579 env.process(); 580 writer.flush(); 581 } 582 finally 583 { 584 writer.close(); 585 } 586 587 log("Output: " + outFile, Project.MSG_INFO ); 588 589 } 590 } 591 catch (SAXParseException spe) 592 { 593 Throwable rootCause = spe; 594 if (spe.getException() != null) 595 rootCause = spe.getException(); 596 log("XML parsing error in " + inFile.getAbsolutePath(), Project.MSG_ERR); 597 log("Line number " + spe.getLineNumber()); 598 log("Column number " + spe.getColumnNumber()); 599 throw new BuildException(rootCause, getLocation()); 600 } 601 catch (Throwable e) 602 { 603 if (outFile != null ) outFile.delete(); 604 e.printStackTrace(); 605 throw new BuildException(e, getLocation()); 606 } 607 } 608 609 private void generateModels() 610 { 611 StringTokenizer modelTokenizer = new StringTokenizer(models, ",; "); 612 while(modelTokenizer.hasMoreTokens()) 613 { 614 String modelSpec = modelTokenizer.nextToken(); 615 String name = null; 616 String clazz = null; 617 618 int sep = modelSpec.indexOf('='); 619 if(sep == -1) 620 { 621 clazz = modelSpec; 623 int dot = clazz.lastIndexOf('.'); 624 if(dot == -1) 625 { 626 name = clazz; 628 } 629 else 630 { 631 name = clazz.substring(dot + 1); 632 } 633 } 634 else 635 { 636 name = modelSpec.substring(0, sep); 637 clazz = modelSpec.substring(sep + 1); 638 } 639 try 640 { 641 modelsMap.put(name, ClassUtil.forName(clazz).newInstance()); 642 } 643 catch(Exception e) 644 { 645 throw new BuildException(e); 646 } 647 } 648 } 649 650 653 private void ensureDirectoryFor( File targetFile ) throws BuildException 654 { 655 File directory = new File( targetFile.getParent() ); 656 if (!directory.exists()) 657 { 658 if (!directory.mkdirs()) 659 { 660 throw new BuildException("Unable to create directory: " 661 + directory.getAbsolutePath(), getLocation()); 662 } 663 } 664 } 665 666 private static TemplateModel wrapMap(Map table) 667 { 668 SimpleHash model = new SimpleHash(); 669 for (Iterator it = table.keySet().iterator(); it.hasNext();) 670 { 671 Object key = it.next(); 672 Object value = table.get(key); 673 model.put(key.toString(), new SimpleScalar(value.toString())); 674 } 675 return model; 676 } 677 678 protected void insertDefaults(Map root) 679 { 680 root.put("properties", propertiesTemplate); 681 root.put("userProperties", userPropertiesTemplate); 682 if (projectTemplate != null) { 683 root.put("project", projectTemplate); 684 root.put("project_node", projectNode); 685 } 686 if(modelsMap.size() > 0) 687 { 688 for (Iterator it = modelsMap.entrySet().iterator(); it.hasNext();) 689 { 690 Map.Entry entry = (Map.Entry) it.next(); 691 root.put(entry.getKey(), entry.getValue()); 692 } 693 } 694 } 695 696 } 697 | Popular Tags |