Home » freemarker-2.3.13 » freemarker.ext.ant » [javadoc | source]

    1   /*
    2    * Copyright (c) 2003 The Visigoth Software Society. All rights
    3    * reserved.
    4    *
    5    * Redistribution and use in source and binary forms, with or without
    6    * modification, are permitted provided that the following conditions
    7    * are met:
    8    *
    9    * 1. Redistributions of source code must retain the above copyright
   10    *    notice, this list of conditions and the following disclaimer.
   11    *
   12    * 2. Redistributions in binary form must reproduce the above copyright
   13    *    notice, this list of conditions and the following disclaimer in
   14    *    the documentation and/or other materials provided with the
   15    *    distribution.
   16    *
   17    * 3. The end-user documentation included with the redistribution, if
   18    *    any, must include the following acknowledgement:
   19    *       "This product includes software developed by the
   20    *        Visigoth Software Society (http://www.visigoths.org/)."
   21    *    Alternately, this acknowledgement may appear in the software itself,
   22    *    if and wherever such third-party acknowledgements normally appear.
   23    *
   24    * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
   25    *    project contributors may be used to endorse or promote products derived
   26    *    from this software without prior written permission. For written
   27    *    permission, please contact visigoths@visigoths.org.
   28    *
   29    * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
   30    *    nor may "FreeMarker" or "Visigoth" appear in their names
   31    *    without prior written permission of the Visigoth Software Society.
   32    *
   33    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   34    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   35    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   36    * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
   37    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   38    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   39    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   40    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   41    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   42    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   43    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44    * SUCH DAMAGE.
   45    * ====================================================================
   46    *
   47    * This software consists of voluntary contributions made by many
   48    * individuals on behalf of the Visigoth Software Society. For more
   49    * information on the Visigoth Software Society, please see
   50    * http://www.visigoths.org/
   51    */
   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   /**
   76    * <p>This is an <a href="http://jakarta.apache.org/ant/" target="_top">Ant</a> task for transforming
   77    * XML documents using FreeMarker templates. It uses the adapter class
   78    * {@link NodeListModel}. It will read a set of XML documents, and pass them to
   79    * the template for processing, building the corresponding output files in the
   80    * destination directory.</p>
   81    * <p>It makes the following variables available to the template in the data model:</p>
   82    * <ul>
   83    * <li><tt>document</tt>: <em>Deprecated!</em> The DOM tree of the currently processed XML file wrapped
   84         with the legacy {@link freemarker.ext.xml.NodeListModel}.
   85         For new projects you should use the <tt>.node</tt> instead, which initially
   86         contains the DOM Document wrapped with {@link freemarker.ext.dom.NodeModel}.</li>
   87    * <li><tt>properties</tt>: a {@link freemarker.template.SimpleHash} containing
   88    * properties of the project that executes the task</li>
   89    * <li><tt>userProperties</tt>: a {@link freemarker.template.SimpleHash} containing
   90    * user properties of the project that executes the task</li>
   91    * <li><tt>project</tt>: the DOM tree of the XML file specified by the
   92    * <tt>projectfile</tt>. It will not be available if you didn't specify the
   93    * <tt>projectfile</tt> attribute.</li>
   94    * <li>further custom models can be instantiated and made available to the 
   95    * templates using the <tt>models</tt> attribute.</li>
   96    * </ul>
   97    * <p>It supports the following attributes:</p>
   98    * <table border="1" cellpadding="2" cellspacing="0">
   99    *   <tr>
  100    *     <th valign="top" align="left">Attribute</th>
  101    *     <th valign="top" align="left">Description</th>
  102    *     <th valign="top">Required</th>
  103    *   </tr>
  104    *   <tr>
  105    *     <td valign="top">basedir</td>
  106    *     <td valign="top">location of the XML files. Defaults to the project's
  107    *       basedir.</td>
  108    *     <td align="center" valign="top">No</td>
  109    *   </tr>
  110    *   <tr>
  111    *     <td valign="top">destdir</td>
  112    *     <td valign="top">location to store the generated files.</td>
  113    *     <td align="center" valign="top">Yes</td>
  114    *   </tr>
  115    *   <tr>
  116    *     <td valign="top">includes</td>
  117    *     <td valign="top">comma-separated list of patterns of files that must be
  118    *       included; all files are included when omitted.</td>
  119    *     <td valign="top" align="center">No</td>
  120    *   </tr>
  121    *   <tr>
  122    *     <td valign="top">includesfile</td>
  123    *     <td valign="top">the name of a file that contains
  124    *       include patterns.</td>
  125    *     <td valign="top" align="center">No</td>
  126    *   </tr>
  127    *   <tr>
  128    *     <td valign="top">excludes</td>
  129    *     <td valign="top">comma-separated list of patterns of files that must be
  130    *       excluded; no files (except default excludes) are excluded when omitted.</td>
  131    *     <td valign="top" align="center">No</td>
  132    *   </tr>
  133    *   <tr>
  134    *     <td valign="top">excludesfile</td>
  135    *     <td valign="top">the name of a file that contains
  136    *       exclude patterns.</td>
  137    *     <td valign="top" align="center">No</td>
  138    *   </tr>
  139    *   <tr>
  140    *     <td valign="top">defaultexcludes</td>
  141    *     <td valign="top">indicates whether default excludes should be used
  142    *       (<code>yes</code> | <code>no</code>); default excludes are used when omitted.</td>
  143    *     <td valign="top" align="center">No</td>
  144    *   </tr>
  145    *   <tr>
  146    *     <td valign="top">extension</td>
  147    *     <td valign="top">extension of generated files. Defaults to .html.</td>
  148    *     <td valign="top" align="center">No</td>
  149    *   </tr>
  150    *   <tr>
  151    *     <td valign="top">template</td>
  152    *     <td valign="top">name of the FreeMarker template file that will be
  153    *       applied by default to XML files</td>
  154    *     <td valign="top" align="center">No</td>
  155    *   </tr>
  156    *   <tr>
  157    *     <td valign="top">templateDir</td>
  158    *     <td valign="top">location of the FreeMarker template(s) to be used, defaults
  159    *                       to the project's baseDir</td>
  160    *     <td valign="top" align="center">No</td>
  161    *   </tr>
  162    *   <tr>
  163    *     <td valign="top">projectfile</td>
  164    *     <td valign="top">path to the project file. The poject file must be an XML file.
  165    *       If omitted, it will not be available to templates </td>
  166    *     <td valign="top" align="center">No</td>
  167    *   </tr>
  168    *   <tr>
  169    *     <td valign="top">incremental</td>
  170    *     <td valign="top">indicates whether all files should be regenerated (no), or
  171    *       only those that are older than the XML file, the template file, or the
  172    *       project file (yes). Defaults to yes. </td>
  173    *     <td valign="top" align="center">No</td>
  174    *   </tr>
  175    *   <tr>
  176    *     <td valign="top">encoding</td>
  177    *     <td valign="top">The encoding of the output files. Defaults to platform
  178    *       default encoding.</td>
  179    *     <td valign="top" align="center">No</td>
  180    *   </tr>
  181    *   <tr>
  182    *     <td valign="top">templateEncoding</td>
  183    *     <td valign="top">The encoding of the template files. Defaults to platform
  184    *       default encoding.</td>
  185    *     <td valign="top" align="center">No</td>
  186    *   </tr>
  187    *   <tr>
  188    *     <td valign="top">validation</td>
  189    *     <td valign="top">Whether to validate the XML input. Defaults to off.</td>
  190    *     <td valign="top" align="center">No</td>
  191    *   </tr>
  192    *   <tr>
  193    *     <td valign="top">models</td>
  194    *     <td valign="top">A list of [name=]className pairs separated by spaces,
  195    *      commas, or semicolons that specifies further models that should be 
  196    *      available to templates. If name is omitted, the unqualified class name
  197    *      is used as the name. Every class that is specified must implement the
  198    *      TemplateModel interface and have a no-args constructor.</td>
  199    *     <td valign="top" align="center">No</td>
  200    *   </tr>
  201    * </table>
  202    * 
  203    * <p>It supports the following nesed elements:</p>
  204    * <table border="1" cellpadding="2" cellspacing="0">
  205    *   <tr>
  206    *     <th valign="top" align="left">Element</th>
  207    *     <th valign="top" align="left">Description</th>
  208    *     <th valign="top">Required</th>
  209    *   </tr>
  210    *   <tr>
  211    *     <td valign="top">prepareModel</td>
  212    *     <td valign="top">
  213    *      This element executes Jython script before the processing of each XML
  214    *      files, that you can use to modify the data model.
  215    *      You either enter the Jython script directly nested into this
  216    *      element, or specify a Jython script file with the <tt>file</tt>
  217    *      attribute.
  218    *      The following variables are added to the Jython runtime's local
  219    *      namespace before the script is invoked:
  220    *      <ul>
  221    *        <li><tt>model</tt>: The data model as <code>java.util.HashMap</code>.
  222    *           You can read and modify the data model with this variable.
  223    *        <li><tt>doc</tt>: The XML document as <code>org.w3c.dom.Document</code>.
  224    *        <li><tt>project</tt>: The project document (if used) as
  225    *           <code>org.w3c.dom.Document</code>.
  226    *      </ul>
  227    *      <i>If this element is used, Jython classes (tried with Jython 2.1)
  228    *      must be available.</i>
  229    *    </td>
  230    *    <td valign="top" align="center">No</td>
  231    *   </tr>
  232    *   <tr>
  233    *     <td valign="top">prepareEnvironment</td>
  234    *     <td valign="top">This element executes Jython script before the processing
  235    *      of each XML files, that you can use to modify the freemarker environment
  236    *      ({@link freemarker.core.Environment}). The script is executed after the
  237    *      <tt>prepareModel</tt> element. The accessible Jython variables are the
  238    *      same as with the <tt>prepareModel</tt> element, except that there is no
  239    *      <tt>model</tt> variable, but there is <tt>env</tt> variable, which is
  240    *      the FreeMarker environment ({@link freemarker.core.Environment}).
  241    *      <i>If this element is used, Jython classes (tried with Jython 2.1)
  242    *      must be available.</i>
  243    *    </td>
  244    *    <td valign="top" align="center">No</td>
  245    *   </tr>
  246    * </table>
  247    * 
  248    * @author Attila Szegedi
  249    * @author Jonathan Revusky, jon@revusky.com
  250    * @deprecated <a href="http://fmpp.sourceforge.net">FMPP</a> is a more complete solution.
  251    * @version $Id: FreemarkerXmlTask.java,v 1.58.2.1 2006/04/26 11:07:58 revusky Exp $
  252    */
  253   public class FreemarkerXmlTask
  254   extends
  255       MatchingTask
  256   {
  257       private JythonAntTask prepareModel;
  258       private JythonAntTask prepareEnvironment;
  259       private final DocumentBuilderFactory builderFactory;
  260       private DocumentBuilder builder;
  261       
  262       /** the {@link Configuration} used by this task. */
  263       private Configuration cfg = new Configuration();
  264       
  265       /** the destination directory */
  266       private File destDir;
  267   
  268       /** the base directory */
  269       private File baseDir;
  270   
  271       //Where the templates live
  272       
  273       private File templateDir;
  274       
  275       /** the template= attribute */
  276       private String templateName;
  277   
  278       /** The template in its parsed form */
  279       private Template parsedTemplate;
  280   
  281       /** last modified of the template sheet */
  282       private long templateFileLastModified = 0;
  283   
  284       /** the projectFile= attribute */
  285       private String projectAttribute = null;
  286   
  287       private File projectFile = null;
  288   
  289       /** The DOM tree of the project wrapped into FreeMarker TemplateModel */
  290       private TemplateModel projectTemplate;
  291       // The DOM tree wrapped using the freemarker.ext.dom wrapping.
  292       private TemplateNodeModel projectNode;
  293       private TemplateModel propertiesTemplate;
  294       private TemplateModel userPropertiesTemplate;
  295   
  296       /** last modified of the project file if it exists */
  297       private long projectFileLastModified = 0;
  298   
  299       /** check the last modified date on files. defaults to true */
  300       private boolean incremental = true;
  301   
  302       /** the default output extension is .html */
  303       private String extension = ".html";
  304   
  305       private String encoding = SecurityUtilities.getSystemProperty("file.encoding");
  306       private String templateEncoding = encoding;
  307       private boolean validation = false;
  308   
  309       private String models = "";
  310       private final Map modelsMap = new HashMap();
  311       
  312       
  313       
  314       /**
  315        * Constructor creates the SAXBuilder.
  316        */
  317       public FreemarkerXmlTask()
  318       {
  319           builderFactory = DocumentBuilderFactory.newInstance();
  320           builderFactory.setNamespaceAware(true);
  321       }
  322   
  323       /**
  324        * Set the base directory. Defaults to <tt>.</tt>
  325        */
  326       public void setBasedir(File dir)
  327       {
  328           baseDir = dir;
  329       }
  330   
  331       /**
  332        * Set the destination directory into which the generated
  333        * files should be copied to
  334        * @param dir the name of the destination directory
  335        */
  336       public void setDestdir(File dir)
  337       {
  338           destDir = dir;
  339       }
  340   
  341       /**
  342        * Set the output file extension. <tt>.html</tt> by default.
  343        */
  344       public void setExtension(String extension)
  345       {
  346           this.extension = extension;
  347       }
  348   
  349       public void setTemplate(String templateName) {
  350           this.templateName = templateName;
  351       }
  352       
  353       public void setTemplateDir(File templateDir) throws BuildException {
  354           this.templateDir = templateDir;
  355           try {
  356               cfg.setDirectoryForTemplateLoading(templateDir);
  357           } catch (Exception e) {
  358               throw new BuildException(e);
  359           }
  360       }
  361   
  362       /**
  363        * Set the path to the project XML file
  364        */
  365       public void setProjectfile(String projectAttribute)
  366       {
  367           this.projectAttribute = projectAttribute;
  368       }
  369   
  370       /**
  371        * Turn on/off incremental processing. On by default
  372        */
  373       public void setIncremental(String incremental)
  374       {
  375           this.incremental = !(incremental.equalsIgnoreCase("false") || incremental.equalsIgnoreCase("no") || incremental.equalsIgnoreCase("off"));
  376       }
  377   
  378       /**
  379        * Set encoding for generated files. Defaults to platform default encoding.
  380        */
  381       public void setEncoding(String encoding)
  382       {
  383           this.encoding = encoding;
  384       }
  385   
  386       public void setTemplateEncoding(String inputEncoding)
  387       {
  388           this.templateEncoding = inputEncoding;
  389       }
  390       
  391       /**
  392        * Sets whether to validate the XML input.
  393        */
  394       public void setValidation(boolean validation) 
  395       {
  396           this.validation = validation;
  397       }
  398   
  399       public void setModels(String models)
  400       {
  401           this.models = models;
  402       }
  403       
  404       public void execute() throws BuildException
  405       {
  406           DirectoryScanner scanner;
  407           String[]         list;
  408   
  409           if (baseDir == null)
  410           {
  411               baseDir = getProject().getBaseDir();
  412           }
  413           if (destDir == null )
  414           {
  415               String msg = "destdir attribute must be set!";
  416               throw new BuildException(msg, getLocation());
  417           }
  418           
  419           File templateFile = null;
  420   
  421           if (templateDir == null) {
  422               if (templateName != null) {
  423                   templateFile = new File(templateName);
  424                   if (!templateFile.isAbsolute()) {
  425                       templateFile = new File(getProject().getBaseDir(), templateName);
  426                   }
  427                   templateDir = templateFile.getParentFile();
  428                   templateName = templateFile.getName();
  429               }
  430               else {
  431                   templateDir = baseDir;
  432               }
  433               setTemplateDir(templateDir);
  434           } else if (templateName != null) {
  435               if (new File(templateName).isAbsolute()) {
  436                   throw new BuildException("Do not specify an absolute location for the template as well as a templateDir");
  437               }
  438               templateFile = new File(templateDir, templateName);
  439           }
  440           if (templateFile != null) {
  441               templateFileLastModified = templateFile.lastModified();
  442           }
  443   
  444           try {
  445               if (templateName != null) {
  446                   parsedTemplate = cfg.getTemplate(templateName, templateEncoding);
  447               }
  448           }
  449           catch (IOException ioe) {
  450               throw new BuildException(ioe.toString());
  451           }
  452           // get the last modification of the template
  453           log("Transforming into: " + destDir.getAbsolutePath(), Project.MSG_INFO);
  454   
  455           // projectFile relative to baseDir
  456           if (projectAttribute != null && projectAttribute.length() > 0)
  457           {
  458               projectFile = new File(baseDir, projectAttribute);
  459               if (projectFile.isFile())
  460                   projectFileLastModified = projectFile.lastModified();
  461               else
  462               {
  463                   log ("Project file is defined, but could not be located: " +
  464                        projectFile.getAbsolutePath(), Project.MSG_INFO );
  465                   projectFile = null;
  466               }
  467           }
  468   
  469           generateModels();
  470           
  471           // find the files/directories
  472           scanner = getDirectoryScanner(baseDir);
  473   
  474           propertiesTemplate = wrapMap(project.getProperties());
  475           userPropertiesTemplate = wrapMap(project.getUserProperties());
  476   
  477           builderFactory.setValidating(validation);
  478           try
  479           {
  480               builder = builderFactory.newDocumentBuilder();
  481           }
  482           catch(ParserConfigurationException e)
  483           {
  484               throw new BuildException("Could not create document builder", e, getLocation());
  485           }
  486   
  487           // get a list of files to work on
  488           list = scanner.getIncludedFiles();
  489           
  490           
  491           for (int i = 0;i < list.length; ++i)
  492           {
  493               process(baseDir, list[i], destDir);
  494           }
  495       }
  496       
  497       public void addConfiguredJython(JythonAntTask jythonAntTask) {
  498           this.prepareEnvironment = jythonAntTask;
  499       }
  500   
  501       public void addConfiguredPrepareModel(JythonAntTask prepareModel) {
  502           this.prepareModel = prepareModel;
  503       }
  504   
  505       public void addConfiguredPrepareEnvironment(JythonAntTask prepareEnvironment) {
  506           this.prepareEnvironment = prepareEnvironment;
  507       }
  508       
  509       /**
  510        * Process an XML file using FreeMarker
  511        */
  512       private void process(File baseDir, String xmlFile, File destDir)
  513       throws BuildException
  514       {
  515           File outFile=null;
  516           File inFile=null;
  517           try
  518           {
  519               // the current input file relative to the baseDir
  520               inFile = new File(baseDir,xmlFile);
  521               // the output file relative to basedir
  522               outFile = new File(destDir,
  523                                  xmlFile.substring(0,
  524                                                    xmlFile.lastIndexOf('.')) + extension);
  525   
  526               // only process files that have changed
  527               if (!incremental ||
  528                   (inFile.lastModified() > outFile.lastModified() ||
  529                    templateFileLastModified > outFile.lastModified() ||
  530                    projectFileLastModified > outFile.lastModified()))
  531               {
  532                   ensureDirectoryFor(outFile);
  533   
  534                   //-- command line status
  535                   log("Input:  " + xmlFile, Project.MSG_INFO );
  536                   
  537                   if (projectTemplate == null && projectFile != null) {
  538                       Document doc = builder.parse(projectFile);
  539                       projectTemplate = new NodeListModel(builder.parse(projectFile));
  540                       projectNode = NodeModel.wrap(doc);
  541                   }
  542   
  543                   // Build the file DOM
  544                   Document docNode = builder.parse(inFile);
  545                   
  546                   TemplateModel document = new NodeListModel(docNode);
  547                   TemplateNodeModel docNodeModel = NodeModel.wrap(docNode);
  548                   HashMap root = new HashMap();
  549                   root.put("document", document);
  550                   insertDefaults(root);
  551   
  552                   // Process the template and write out
  553                   // the result as the outFile.
  554                   Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), encoding));
  555                   try
  556                   {
  557                       if (parsedTemplate == null) {
  558                           throw new BuildException("No template file specified in build script or in XML file");
  559                       }
  560                       if (prepareModel != null) {
  561                           Map vars = new HashMap();
  562                           vars.put("model", root);
  563                           vars.put("doc", docNode);
  564                           if (projectNode != null) {
  565                               vars.put("project", ((NodeModel) projectNode).getNode());
  566                           }
  567                           prepareModel.execute(vars);
  568                       }
  569                       freemarker.core.Environment env = parsedTemplate.createProcessingEnvironment(root, writer);
  570                       env.setCurrentVisitorNode(docNodeModel);
  571                       if (prepareEnvironment != null) {
  572                           Map vars = new HashMap();
  573                           vars.put("env", env);
  574                           vars.put("doc", docNode);
  575                           if (projectNode != null) {
  576                               vars.put("project", ((NodeModel) projectNode).getNode());
  577                           }
  578                           prepareEnvironment.execute(vars);
  579                       }
  580                       env.process();
  581                       writer.flush();
  582                   }
  583                   finally
  584                   {
  585                       writer.close();
  586                   }
  587   
  588                   log("Output: " + outFile, Project.MSG_INFO );
  589                   
  590               }
  591           }
  592           catch (SAXParseException spe)
  593           {
  594               Throwable rootCause = spe;
  595               if (spe.getException() != null)
  596                   rootCause = spe.getException();
  597               log("XML parsing error in " + inFile.getAbsolutePath(), Project.MSG_ERR);
  598               log("Line number " + spe.getLineNumber());
  599               log("Column number " + spe.getColumnNumber());
  600               throw new BuildException(rootCause, getLocation());
  601           }
  602           catch (Throwable e)
  603           {
  604               if (outFile != null ) {
  605                   if(!outFile.delete() && outFile.exists()) {
  606                       log("Failed to delete " + outFile, Project.MSG_WARN);
  607                   }
  608               }
  609               e.printStackTrace();
  610               throw new BuildException(e, getLocation());
  611           }
  612       }
  613   
  614       private void generateModels()
  615       {
  616           StringTokenizer modelTokenizer = new StringTokenizer(models, ",; ");
  617           while(modelTokenizer.hasMoreTokens())
  618           {
  619               String modelSpec = modelTokenizer.nextToken();
  620               String name = null;
  621               String clazz = null;
  622               
  623               int sep = modelSpec.indexOf('=');
  624               if(sep == -1)
  625               {
  626                   // No explicit name - use unqualified class name
  627                   clazz = modelSpec;
  628                   int dot = clazz.lastIndexOf('.');
  629                   if(dot == -1)
  630                   {
  631                       // clazz in the default package
  632                       name = clazz;
  633                   }
  634                   else
  635                   {
  636                       name = clazz.substring(dot + 1);
  637                   }
  638               }
  639               else
  640               {
  641                   name = modelSpec.substring(0, sep);
  642                   clazz = modelSpec.substring(sep + 1);
  643               }
  644               try
  645               {
  646                   modelsMap.put(name, ClassUtil.forName(clazz).newInstance());
  647               }
  648               catch(Exception e)
  649               {
  650                   throw new BuildException(e);
  651               }
  652           }
  653       }
  654       
  655       /**
  656        * create directories as needed
  657        */
  658       private void ensureDirectoryFor( File targetFile ) throws BuildException
  659       {
  660           File directory = new File( targetFile.getParent() );
  661           if (!directory.exists())
  662           {
  663               if (!directory.mkdirs())
  664               {
  665                   throw new BuildException("Unable to create directory: "
  666                                            + directory.getAbsolutePath(), getLocation());
  667               }
  668           }
  669       }
  670   
  671       private static TemplateModel wrapMap(Map table)
  672       {
  673           SimpleHash model = new SimpleHash();
  674           for (Iterator it = table.entrySet().iterator(); it.hasNext();)
  675           {
  676               Map.Entry entry = (Map.Entry)it.next();
  677               model.put(String.valueOf(entry.getKey()), new SimpleScalar(String.valueOf(entry.getValue())));
  678           }
  679           return model;
  680       }
  681   
  682       protected void insertDefaults(Map root) 
  683       {
  684           root.put("properties", propertiesTemplate);
  685           root.put("userProperties", userPropertiesTemplate);
  686           if (projectTemplate != null) {
  687               root.put("project", projectTemplate);
  688               root.put("project_node", projectNode);
  689           }
  690           if(modelsMap.size() > 0)
  691           {
  692               for (Iterator it = modelsMap.entrySet().iterator(); it.hasNext();)
  693               {
  694                   Map.Entry entry = (Map.Entry) it.next();
  695                   root.put(entry.getKey(), entry.getValue());
  696               }
  697           }
  698       }
  699       
  700   }

Home » freemarker-2.3.13 » freemarker.ext.ant » [javadoc | source]