Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (c) 2003 The Visigoth Software Society. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
  *
  * 3. The end-user documentation included with the redistribution, if
  *    any, must include the following acknowledgement:
  *       "This product includes software developed by the
  *        Visigoth Software Society (http://www.visigoths.org/)."
  *    Alternately, this acknowledgement may appear in the software itself,
  *    if and wherever such third-party acknowledgements normally appear.
  *
  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
  *    project contributors may be used to endorse or promote products derived
  *    from this software without prior written permission. For written
  *    permission, please contact visigoths@visigoths.org.
  *
  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
  *    nor may "FreeMarker" or "Visigoth" appear in their names
  *    without prior written permission of the Visigoth Software Society.
  *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * ====================================================================
  *
  * This software consists of voluntary contributions made by many
  * individuals on behalf of the Visigoth Software Society. For more
  * information on the Visigoth Software Society, please see
  * http://www.visigoths.org/
  */
 
 package freemarker.ext.ant;
 
 import java.io.*;
 import java.util.*;
 
 import org.w3c.dom.*;
 
 import  org.apache.tools.ant.BuildException;
 import  org.apache.tools.ant.DirectoryScanner;
 import  org.apache.tools.ant.Project;
 import  org.apache.tools.ant.taskdefs.MatchingTask;

This is an Ant task for transforming XML documents using FreeMarker templates. It uses the adapter class NodeListModel. It will read a set of XML documents, and pass them to the template for processing, building the corresponding output files in the destination directory.

It makes the following variables available to the template in the data model:

  • document: Deprecated! The DOM tree of the currently processed XML file wrapped with the legacy freemarker.ext.xml.NodeListModel. For new projects you should use the .node instead, which initially contains the DOM Document wrapped with freemarker.ext.dom.NodeModel.
  • properties: a freemarker.template.SimpleHash containing properties of the project that executes the task
  • userProperties: a freemarker.template.SimpleHash containing user properties of the project that executes the task
  • project: the DOM tree of the XML file specified by the projectfile. It will not be available if you didn't specify the projectfile attribute.
  • further custom models can be instantiated and made available to the templates using the models attribute.

It supports the following attributes:

AttributeDescriptionRequired
basedirlocation of the XML files. Defaults to the project's basedir.No
destdirlocation to store the generated files.Yes
includescomma-separated list of patterns of files that must be included; all files are included when omitted.No
includesfilethe name of a file that contains include patterns.No
excludescomma-separated list of patterns of files that must be excluded; no files (except default excludes) are excluded when omitted.No
excludesfilethe name of a file that contains exclude patterns.No
defaultexcludesindicates whether default excludes should be used (yes | no); default excludes are used when omitted.No
extensionextension of generated files. Defaults to .html.No
templatename of the FreeMarker template file that will be applied by default to XML filesNo
templateDirlocation of the FreeMarker template(s) to be used, defaults to the project's baseDirNo
projectfilepath to the project file. The poject file must be an XML file. If omitted, it will not be available to templates No
incrementalindicates whether all files should be regenerated (no), or only those that are older than the XML file, the template file, or the project file (yes). Defaults to yes. No
encodingThe encoding of the output files. Defaults to platform default encoding.No
templateEncodingThe encoding of the template files. Defaults to platform default encoding.No
validationWhether to validate the XML input. Defaults to off.No
modelsA list of [name=]className pairs separated by spaces, commas, or semicolons that specifies further models that should be available to templates. If name is omitted, the unqualified class name is used as the name. Every class that is specified must implement the TemplateModel interface and have a no-args constructor.No

It supports the following nesed elements:

ElementDescriptionRequired
prepareModel This element executes Jython script before the processing of each XML files, that you can use to modify the data model. You either enter the Jython script directly nested into this element, or specify a Jython script file with the file attribute. The following variables are added to the Jython runtime's local namespace before the script is invoked:
  • model: The data model as java.util.HashMap. You can read and modify the data model with this variable.
  • doc: The XML document as org.w3c.dom.Document.
  • project: The project document (if used) as org.w3c.dom.Document.
If this element is used, Jython classes (tried with Jython 2.1) must be available.
No
prepareEnvironmentThis element executes Jython script before the processing of each XML files, that you can use to modify the freemarker environment (freemarker.core.Environment). The script is executed after the prepareModel element. The accessible Jython variables are the same as with the prepareModel element, except that there is no model variable, but there is env variable, which is the FreeMarker environment (freemarker.core.Environment). If this element is used, Jython classes (tried with Jython 2.1) must be available. No

Deprecated:
FMPP is a more complete solution.
Author(s):
Attila Szegedi
Jonathan Revusky, jon@revusky.com
Version:
$Id: FreemarkerXmlTask.java,v 1.58.2.1 2006/04/26 11:07:58 revusky Exp $
public class FreemarkerXmlTask
extends
    MatchingTask
    private JythonAntTask prepareModel;
    private final DocumentBuilderFactory builderFactory;
    private DocumentBuilder builder;
    
    
the Configuration used by this task.
    private Configuration cfg = new Configuration();
    
    
the destination directory
    private File destDir;

    
the base directory
    private File baseDir;
    //Where the templates live
    
    private File templateDir;
    
    
the template= attribute
    private String templateName;

    
The template in its parsed form
    private Template parsedTemplate;

    
last modified of the template sheet
    private long templateFileLastModified = 0;

    
the projectFile= attribute
    private String projectAttribute = null;
    private File projectFile = null;

    
The DOM tree of the project wrapped into FreeMarker TemplateModel
    // The DOM tree wrapped using the freemarker.ext.dom wrapping.
    private TemplateModel userPropertiesTemplate;

    
last modified of the project file if it exists
    private long projectFileLastModified = 0;

    
check the last modified date on files. defaults to true
    private boolean incremental = true;

    
the default output extension is .html
    private String extension = ".html";
    private String encoding = SecurityUtilities.getSystemProperty("file.encoding");
    private String templateEncoding = ;
    private boolean validation = false;
    private String models = "";
    private final Map modelsMap = new HashMap();
    
    
    
    
Constructor creates the SAXBuilder.
    public FreemarkerXmlTask()
    {
         = DocumentBuilderFactory.newInstance();
        .setNamespaceAware(true);
    }

    
Set the base directory. Defaults to .
    public void setBasedir(File dir)
    {
         = dir;
    }

    
Set the destination directory into which the generated files should be copied to

Parameters:
dir the name of the destination directory
    public void setDestdir(File dir)
    {
         = dir;
    }

    
Set the output file extension. .html by default.
    public void setExtension(String extension)
    {
        this. = extension;
    }
    public void setTemplate(String templateName) {
        this. = templateName;
    }
    
    public void setTemplateDir(File templateDirthrows BuildException {
        this. = templateDir;
        try {
            .setDirectoryForTemplateLoading(templateDir);
        } catch (Exception e) {
            throw new BuildException(e);
        }
    }

    
Set the path to the project XML file
    public void setProjectfile(String projectAttribute)
    {
        this. = projectAttribute;
    }

    
Turn on/off incremental processing. On by default
    public void setIncremental(String incremental)
    {
        this. = !(incremental.equalsIgnoreCase("false") || incremental.equalsIgnoreCase("no") || incremental.equalsIgnoreCase("off"));
    }

    
Set encoding for generated files. Defaults to platform default encoding.
    public void setEncoding(String encoding)
    {
        this. = encoding;
    }
    public void setTemplateEncoding(String inputEncoding)
    {
        this. = inputEncoding;
    }
    
    
Sets whether to validate the XML input.
    public void setValidation(boolean validation
    {
        this. = validation;
    }
    public void setModels(String models)
    {
        this. = models;
    }
    
    public void execute() throws BuildException
    {
        DirectoryScanner scanner;
        String[]         list;
        if ( == null)
        {
             = getProject().getBaseDir();
        }
        if ( == null )
        {
            String msg = "destdir attribute must be set!";
            throw new BuildException(msggetLocation());
        }
        
        File templateFile = null;
        if ( == null) {
            if ( != null) {
                templateFile = new File();
                if (!templateFile.isAbsolute()) {
                    templateFile = new File(getProject().getBaseDir(), );
                }
                 = templateFile.getParentFile();
                 = templateFile.getName();
            }
            else {
                 = ;
            }
            setTemplateDir();
        } else if ( != null) {
            if (new File().isAbsolute()) {
                throw new BuildException("Do not specify an absolute location for the template as well as a templateDir");
            }
            templateFile = new File();
        }
        if (templateFile != null) {
             = templateFile.lastModified();
        }
        try {
            if ( != null) {
                 = .getTemplate();
            }
        }
        catch (IOException ioe) {
            throw new BuildException(ioe.toString());
        }
        // get the last modification of the template
        log("Transforming into: " + .getAbsolutePath(), Project.MSG_INFO);
        // projectFile relative to baseDir
        if ( != null && .length() > 0)
        {
             = new File();
            if (.isFile())
                 = .lastModified();
            else
            {
                log ("Project file is defined, but could not be located: " +
                     .getAbsolutePath(), Project.MSG_INFO );
                 = null;
            }
        }
        generateModels();
        
        // find the files/directories
        scanner = getDirectoryScanner();
         = wrapMap(project.getProperties());
         = wrapMap(project.getUserProperties());
        try
        {
             = .newDocumentBuilder();
        }
        catch(ParserConfigurationException e)
        {
            throw new BuildException("Could not create document builder"egetLocation());
        }
        // get a list of files to work on
        list = scanner.getIncludedFiles();
        
        
        for (int i = 0;i < list.length; ++i)
        {
            process(list[i], );
        }
    }
    
    public void addConfiguredJython(JythonAntTask jythonAntTask) {
        this. = jythonAntTask;
    }
    public void addConfiguredPrepareModel(JythonAntTask prepareModel) {
        this. = prepareModel;
    }
    public void addConfiguredPrepareEnvironment(JythonAntTask prepareEnvironment) {
        this. = prepareEnvironment;
    }
    
    
Process an XML file using FreeMarker
    private void process(File baseDirString xmlFileFile destDir)
    throws BuildException
    {
        File outFile=null;
        File inFile=null;
        try
        {
            // the current input file relative to the baseDir
            inFile = new File(baseDir,xmlFile);
            // the output file relative to basedir
            outFile = new File(destDir,
                               xmlFile.substring(0,
                                                 xmlFile.lastIndexOf('.')) + );
            // only process files that have changed
            if (! ||
                (inFile.lastModified() > outFile.lastModified() ||
                  > outFile.lastModified() ||
                  > outFile.lastModified()))
            {
                ensureDirectoryFor(outFile);
                //-- command line status
                log("Input:  " + xmlFile, Project.MSG_INFO );
                
                if ( == null &&  != null) {
                    Document doc = .parse();
                     = new NodeListModel(.parse());
                     = NodeModel.wrap(doc);
                }
                // Build the file DOM
                Document docNode = .parse(inFile);
                
                TemplateModel document = new NodeListModel(docNode);
                TemplateNodeModel docNodeModel = NodeModel.wrap(docNode);
                HashMap root = new HashMap();
                root.put("document"document);
                insertDefaults(root);
                // Process the template and write out
                // the result as the outFile.
                Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), ));
                try
                {
                    if ( == null) {
                        throw new BuildException("No template file specified in build script or in XML file");
                    }
                    if ( != null) {
                        Map vars = new HashMap();
                        vars.put("model"root);
                        vars.put("doc"docNode);
                        if ( != null) {
                            vars.put("project", ((NodeModel).getNode());
                        }
                        .execute(vars);
                    }
                    freemarker.core.Environment env = .createProcessingEnvironment(rootwriter);
                    env.setCurrentVisitorNode(docNodeModel);
                    if ( != null) {
                        Map vars = new HashMap();
                        vars.put("env"env);
                        vars.put("doc"docNode);
                        if ( != null) {
                            vars.put("project", ((NodeModel).getNode());
                        }
                        .execute(vars);
                    }
                    env.process();
                    writer.flush();
                }
                finally
                {
                    writer.close();
                }
                log("Output: " + outFile, Project.MSG_INFO );
                
            }
        }
        catch (SAXParseException spe)
        {
            Throwable rootCause = spe;
            if (spe.getException() != null)
                rootCause = spe.getException();
            log("XML parsing error in " + inFile.getAbsolutePath(), Project.MSG_ERR);
            log("Line number " + spe.getLineNumber());
            log("Column number " + spe.getColumnNumber());
            throw new BuildException(rootCausegetLocation());
        }
        catch (Throwable e)
        {
            if (outFile != null ) {
                if(!outFile.delete() && outFile.exists()) {
                    log("Failed to delete " + outFile, Project.MSG_WARN);
                }
            }
            e.printStackTrace();
            throw new BuildException(egetLocation());
        }
    }
    private void generateModels()
    {
        StringTokenizer modelTokenizer = new StringTokenizer(",; ");
        while(modelTokenizer.hasMoreTokens())
        {
            String modelSpec = modelTokenizer.nextToken();
            String name = null;
            String clazz = null;
            
            int sep = modelSpec.indexOf('=');
            if(sep == -1)
            {
                // No explicit name - use unqualified class name
                clazz = modelSpec;
                int dot = clazz.lastIndexOf('.');
                if(dot == -1)
                {
                    // clazz in the default package
                    name = clazz;
                }
                else
                {
                    name = clazz.substring(dot + 1);
                }
            }
            else
            {
                name = modelSpec.substring(0, sep);
                clazz = modelSpec.substring(sep + 1);
            }
            try
            {
                .put(name, ClassUtil.forName(clazz).newInstance());
            }
            catch(Exception e)
            {
                throw new BuildException(e);
            }
        }
    }
    
    
create directories as needed
    private void ensureDirectoryForFile targetFile ) throws BuildException
    {
        File directory = new FiletargetFile.getParent() );
        if (!directory.exists())
        {
            if (!directory.mkdirs())
            {
                throw new BuildException("Unable to create directory: "
                                         + directory.getAbsolutePath(), getLocation());
            }
        }
    }
    private static TemplateModel wrapMap(Map table)
    {
        SimpleHash model = new SimpleHash();
        for (Iterator it = table.entrySet().iterator(); it.hasNext();)
        {
            Map.Entry entry = (Map.Entry)it.next();
            model.put(String.valueOf(entry.getKey()), new SimpleScalar(String.valueOf(entry.getValue())));
        }
        return model;
    }
    protected void insertDefaults(Map root
    {
        root.put("properties");
        root.put("userProperties");
        if ( != null) {
            root.put("project");
            root.put("project_node");
        }
        if(.size() > 0)
        {
            for (Iterator it = .entrySet().iterator(); it.hasNext();)
            {
                Map.Entry entry = (Map.Entryit.next();
                root.put(entry.getKey(), entry.getValue());
            }
        }
    }
    
New to GrepCode? Check out our FAQ X