FileDocCategorySizeDatePackage
XSLTProcess.javaAPI DocApache Ant 1.7039832Wed Dec 13 06:16:20 GMT 2006org.apache.tools.ant.taskdefs

XSLTProcess

public class XSLTProcess extends MatchingTask implements XSLTLogger
Processes a set of XML documents via XSLT. This is useful for building views of XML based documentation.
since
Ant 1.1
ant.task
name="xslt" category="xml"

Fields Summary
private File
destDir
destination directory
private File
baseDir
where to find the source XML file, default is the project's basedir
private String
xslFile
XSL stylesheet as a filename
private org.apache.tools.ant.types.Resource
xslResource
XSL stylesheet as a {@link org.apache.tools.ant.types.Resource}
private String
targetExtension
extension of the files produced by XSL processing
private String
fileNameParameter
name for XSL parameter containing the filename
private String
fileDirParameter
name for XSL parameter containing the file directory
private Vector
params
additional parameters to be passed to the stylesheets
private File
inFile
Input XML document to be used
private File
outFile
Output file
private String
processor
The name of the XSL processor to use
private org.apache.tools.ant.types.Path
classpath
Classpath to use when trying to load the XSL processor
private XSLTLiaison
liaison
The Liason implementation to use to communicate with the XSL processor
private boolean
stylesheetLoaded
Flag which indicates if the stylesheet has been loaded into the processor
private boolean
force
force output of target files even if they already exist
private Vector
outputProperties
XSL output properties to be used
private org.apache.tools.ant.types.XMLCatalog
xmlCatalog
for resolving entities such as dtds
private static final String
TRAX_LIAISON_CLASS
Name of the TRAX Liaison class
private static final org.apache.tools.ant.util.FileUtils
FILE_UTILS
Utilities used for file operations
private boolean
performDirectoryScan
Whether to style all files in the included directories as well.
private Factory
factory
factory element for TraX processors only
private boolean
reuseLoadedStylesheet
whether to reuse Transformer if transforming multiple files.
private org.apache.tools.ant.AntClassLoader
loader
AntClassLoader for the nested <classpath> - if set.

We keep this here in order to reset the context classloader in execute. We can't use liaison.getClass().getClassLoader() since the actual liaison class may have been loaded by a loader higher up (system classloader, for example).

private org.apache.tools.ant.types.Mapper
mapperElement
Mapper to use when a set of files gets processed.
private org.apache.tools.ant.types.resources.Union
resources
Additional resource collections to process.
private boolean
useImplicitFileset
Whether to use the implicit fileset.
public static final String
PROCESSOR_TRAX
The default processor is trax
Constructors Summary
public XSLTProcess()
Creates a new XSLTProcess Task.


              
      
    
Methods Summary
public voidadd(org.apache.tools.ant.types.ResourceCollection rc)
Adds a collection of resources to style in addition to the given file or the implicit fileset.

param
rc the collection of resources to style
since
Ant 1.7

        resources.add(rc);
    
public voidadd(org.apache.tools.ant.util.FileNameMapper fileNameMapper)
Adds a nested filenamemapper.

param
fileNameMapper the mapper to add
exception
BuildException if more than one mapper is defined
since
Ant 1.7.0

       Mapper mapper = new Mapper(getProject());
       mapper.add(fileNameMapper);
       addMapper(mapper);
    
public voidaddConfiguredStyle(org.apache.tools.ant.types.resources.Resources rc)
Add a nested <style> element.

param
rc the configured Resources object represented as <style>.
since
Ant 1.7

        if (rc.size() != 1) {
            throw new BuildException("The style element must be specified"
                    + " with exactly one nested resource.");
        }
        setXslResource((Resource) rc.iterator().next());
    
public voidaddConfiguredXMLCatalog(org.apache.tools.ant.types.XMLCatalog xmlCatalog)
Add the catalog to our internal catalog

param
xmlCatalog the XMLCatalog instance to use to look up DTDs

        this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog);
    
public voidaddMapper(org.apache.tools.ant.types.Mapper mapper)
Defines the mapper to map source to destination files.

param
mapper the mapper to use
exception
BuildException if more than one mapper is defined
since
Ant 1.6.2

        if (mapperElement != null) {
            throw new BuildException("Cannot define more than one mapper",
                                     getLocation());
        }
        mapperElement = mapper;
    
private voidcheckDest()
Throws a BuildException if the destination directory hasn't been specified.

since
Ant 1.7

        if (destDir == null) {
            String msg = "destdir attributes must be set!";
            throw new BuildException(msg);
        }
    
protected voidconfigureLiaison(java.io.File stylesheet)
Loads the stylesheet and set xsl:param parameters.

param
stylesheet the file from which to load the stylesheet.
exception
BuildException if the stylesheet cannot be loaded.
deprecated
since Ant 1.7

        FileResource fr = new FileResource();
        fr.setProject(getProject());
        fr.setFile(stylesheet);
        configureLiaison(fr);
    
protected voidconfigureLiaison(org.apache.tools.ant.types.Resource stylesheet)
Loads the stylesheet and set xsl:param parameters.

param
stylesheet the resource from which to load the stylesheet.
exception
BuildException if the stylesheet cannot be loaded.
since
Ant 1.7

        if (stylesheetLoaded && reuseLoadedStylesheet) {
            return;
        }
        stylesheetLoaded = true;

        try {
            log("Loading stylesheet " + stylesheet, Project.MSG_INFO);
            // We call liason.configure() and then liaison.setStylesheet()
            // so that the internal variables of liaison can be set up
            if (liaison instanceof XSLTLiaison2) {
                ((XSLTLiaison2) liaison).configure(this);
            }

            if (liaison instanceof XSLTLiaison3) {
                // If we are here we can set the stylesheet as a
                // resource
                ((XSLTLiaison3) liaison).setStylesheet(stylesheet);
            } else {
                // If we are here we cannot set the stylesheet as
                // a resource, but we can set it as a file. So,
                // we make an attempt to get it as a file
                if (stylesheet instanceof FileResource) {
                    liaison.setStylesheet(
                            ((FileResource) stylesheet).getFile());
                } else {
                    throw new BuildException(liaison.getClass().toString()
                            + " accepts the stylesheet only as a file",
                            getLocation());
                }
            }
            for (Enumeration e = params.elements(); e.hasMoreElements();) {
                Param p = (Param) e.nextElement();
                if (p.shouldUse()) {
                    liaison.addParam(p.getName(), p.getExpression());
                }
            }
        } catch (Exception ex) {
            log("Failed to transform using stylesheet " + stylesheet,
                 Project.MSG_INFO);
            throw new BuildException(ex);
        }
    
public org.apache.tools.ant.types.PathcreateClasspath()
Set the optional classpath to the XSL processor

return
a path instance to be configured by the Ant core.

        if (classpath == null) {
            classpath = new Path(getProject());
        }
        return classpath.createPath();
    
public org.apache.tools.ant.taskdefs.XSLTProcess$FactorycreateFactory()
Create the factory element to configure a trax liaison.

return
the newly created factory element.
throws
BuildException if the element is created more than one time.

        if (factory != null) {
            throw new BuildException("'factory' element must be unique");
        }
        factory = new Factory();
        return factory;
    
public org.apache.tools.ant.taskdefs.XSLTProcess$OutputPropertycreateOutputProperty()
Create an instance of an output property to be configured.

return
the newly created output property.
since
Ant 1.5

        OutputProperty p = new OutputProperty();
        outputProperties.addElement(p);
        return p;
    
public org.apache.tools.ant.taskdefs.XSLTProcess$ParamcreateParam()
Create an instance of an XSL parameter for configuration by Ant.

return
an instance of the Param class to be configured.

        Param p = new Param();
        params.addElement(p);
        return p;
    
private voidensureDirectoryFor(java.io.File targetFile)
Ensure the directory exists for a given file

param
targetFile the file for which the directories are required.
exception
BuildException if the directories cannot be created.

        File directory = targetFile.getParentFile();
        if (!directory.exists()) {
            if (!directory.mkdirs()) {
                throw new BuildException("Unable to create directory: "
                                         + directory.getAbsolutePath());
            }
        }
    
public voidexecute()
Executes the task.

exception
BuildException if there is an execution problem.
todo
validate that if either in or our is defined, then both are

        if ("style".equals(getTaskType())) {
            log("Warning: the task name <style> is deprecated. Use <xslt> instead.",
                    Project.MSG_WARN);
        }

        File savedBaseDir = baseDir;

        DirectoryScanner scanner;
        String[]         list;
        String[]         dirs;

        if (xslResource == null && xslFile == null) {
            throw new BuildException("specify the "
                + "stylesheet either as a filename in style "
                + "attribute or as a nested resource", getLocation());

        }
        if (xslResource != null && xslFile != null) {
            throw new BuildException("specify the "
                + "stylesheet either as a filename in style "
                + "attribute or as a nested resource but not "
                + "as both", getLocation());
        }

        if (inFile != null && !inFile.exists()) {
            throw new BuildException(
                "input file " + inFile.toString() + " does not exist", getLocation());
        }

        try {
            if (baseDir == null) {
                baseDir = getProject().resolveFile(".");
            }

            liaison = getLiaison();

            // check if liaison wants to log errors using us as logger
            if (liaison instanceof XSLTLoggerAware) {
                ((XSLTLoggerAware) liaison).setLogger(this);
            }

            log("Using " + liaison.getClass().toString(), Project.MSG_VERBOSE);

            if (xslFile != null) {
                // If we enter here, it means that the stylesheet is supplied
                // via style attribute
                File stylesheet = getProject().resolveFile(xslFile);
                if (!stylesheet.exists()) {
                    stylesheet = FILE_UTILS.resolveFile(baseDir, xslFile);
                    /*
                     * shouldn't throw out deprecation warnings before we know,
                     * the wrong version has been used.
                     */
                    if (stylesheet.exists()) {
                        log("DEPRECATED - the 'style' attribute should be relative "
                                + "to the project's");
                        log("             basedir, not the tasks's basedir.");
                    }
                }
                FileResource fr = new FileResource();
                fr.setProject(getProject());
                fr.setFile(stylesheet);
                xslResource = fr;
            }

            // if we have an in file and out then process them
            if (inFile != null && outFile != null) {
                process(inFile, outFile, xslResource);
                return;
            }

            /*
             * if we get here, in and out have not been specified, we are
             * in batch processing mode.
             */

            //-- make sure destination directory exists...
            checkDest();

            if (useImplicitFileset) {
                scanner = getDirectoryScanner(baseDir);
                log("Transforming into " + destDir, Project.MSG_INFO);

                // Process all the files marked for styling
                list = scanner.getIncludedFiles();
                for (int i = 0; i < list.length; ++i) {
                    process(baseDir, list[i], destDir, xslResource);
                }
                if (performDirectoryScan) {
                    // Process all the directories marked for styling
                    dirs = scanner.getIncludedDirectories();
                    for (int j = 0; j < dirs.length; ++j) {
                        list = new File(baseDir, dirs[j]).list();
                        for (int i = 0; i < list.length; ++i) {
                            process(baseDir, dirs[j] + File.separator + list[i],
                                    destDir, xslResource);
                        }
                    }
                }
            } else { // only resource collections, there better be some
                if (resources.size() == 0) {
                    throw new BuildException("no resources specified");
                }
            }
            processResources(xslResource);
        } finally {
            if (loader != null) {
                loader.resetThreadContextLoader();
                loader.cleanup();
                loader = null;
            }
            liaison = null;
            stylesheetLoaded = false;
            baseDir = savedBaseDir;
        }
    
public org.apache.tools.ant.taskdefs.XSLTProcess$FactorygetFactory()
Get the factory instance configured for this processor

return
the factory instance in use

        return factory;
    
protected XSLTLiaisongetLiaison()
Get the Liason implementation to use in processing.

return
an instance of the XSLTLiason interface.

        // if processor wasn't specified, see if TraX is available.  If not,
        // default it to xalan, depending on which is in the classpath
        if (liaison == null) {
            if (processor != null) {
                try {
                    resolveProcessor(processor);
                } catch (Exception e) {
                    throw new BuildException(e);
                }
            } else {
                try {
                    resolveProcessor(PROCESSOR_TRAX);
                } catch (Throwable e1) {
                    e1.printStackTrace();
                    throw new BuildException(e1);
                }
            }
        }
        return liaison;
    
public java.util.EnumerationgetOutputProperties()
Get an enumeration on the outputproperties.

return
the outputproperties

        return outputProperties.elements();
    
public org.apache.tools.ant.types.XMLCataloggetXMLCatalog()
Get the XML catalog containing entity definitions

return
the XML catalog for the task.

        xmlCatalog.setProject(getProject());
        return xmlCatalog;
    
public voidinit()
Initialize internal instance of XMLCatalog

throws
BuildException on error

        super.init();
        xmlCatalog.setProject(getProject());
    
private java.lang.ClassloadClass(java.lang.String classname)
Load named class either via the system classloader or a given custom classloader. As a side effect, the loader is set as the thread context classloader

param
classname the name of the class to load.
return
the requested class.
exception
Exception if the class could not be loaded.

        if (classpath == null) {
            return Class.forName(classname);
        } else {
            loader = getProject().createClassLoader(classpath);
            loader.setThreadContextLoader();
            Class c = Class.forName(classname, true, loader);
            return c;
        }
    
private voidprocess(java.io.File baseDir, java.lang.String xmlFile, java.io.File destDir, org.apache.tools.ant.types.Resource stylesheet)
Processes the given input XML file and stores the result in the given resultFile.

param
baseDir the base directory for resolving files.
param
xmlFile the input file
param
destDir the destination directory
param
stylesheet the stylesheet to use.
exception
BuildException if the processing fails.


        File   outF = null;
        File   inF = null;

        try {
            long styleSheetLastModified = stylesheet.getLastModified();
            inF = new File(baseDir, xmlFile);

            if (inF.isDirectory()) {
                log("Skipping " + inF + " it is a directory.",
                    Project.MSG_VERBOSE);
                return;
            }

            FileNameMapper mapper = null;
            if (mapperElement != null) {
                mapper = mapperElement.getImplementation();
            } else {
                mapper = new StyleMapper();
            }

            String[] outFileName = mapper.mapFileName(xmlFile);
            if (outFileName == null || outFileName.length == 0) {
                log("Skipping " + inFile + " it cannot get mapped to output.",
                    Project.MSG_VERBOSE);
                return;
            } else if (outFileName == null || outFileName.length > 1) {
                log("Skipping " + inFile + " its mapping is ambiguos.",
                    Project.MSG_VERBOSE);
                return;
            }

            outF = new File(destDir, outFileName[0]);

            if (force
                || inF.lastModified() > outF.lastModified()
                || styleSheetLastModified > outF.lastModified()) {
                ensureDirectoryFor(outF);
                log("Processing " + inF + " to " + outF);

                configureLiaison(stylesheet);
                setLiaisonDynamicFileParameters(liaison, inF);
                liaison.transform(inF, outF);
            }
        } catch (Exception ex) {
            // If failed to process document, must delete target document,
            // or it will not attempt to process it the second time
            log("Failed to process " + inFile, Project.MSG_INFO);
            if (outF != null) {
                outF.delete();
            }

            throw new BuildException(ex);
        }

    
private voidprocess(java.io.File inFile, java.io.File outFile, org.apache.tools.ant.types.Resource stylesheet)
Process the input file to the output file with the given stylesheet.

param
inFile the input file to process.
param
outFile the destination file.
param
stylesheet the stylesheet to use.
exception
BuildException if the processing fails.

        try {
            long styleSheetLastModified = stylesheet.getLastModified();
            log("In file " + inFile + " time: " + inFile.lastModified(),
                Project.MSG_DEBUG);
            log("Out file " + outFile + " time: " + outFile.lastModified(),
                Project.MSG_DEBUG);
            log("Style file " + xslFile + " time: " + styleSheetLastModified,
                Project.MSG_DEBUG);
            if (force || inFile.lastModified() >= outFile.lastModified()
                || styleSheetLastModified >= outFile.lastModified()) {
                ensureDirectoryFor(outFile);
                log("Processing " + inFile + " to " + outFile,
                    Project.MSG_INFO);
                configureLiaison(stylesheet);
                setLiaisonDynamicFileParameters(liaison, inFile);
                liaison.transform(inFile, outFile);
            } else {
                log("Skipping input file " + inFile
                    + " because it is older than output file " + outFile
                    + " and so is the stylesheet " + stylesheet, Project.MSG_DEBUG);
            }
        } catch (Exception ex) {
            log("Failed to process " + inFile, Project.MSG_INFO);
            if (outFile != null) {
                outFile.delete();
            }
            throw new BuildException(ex);
        }
    
private voidprocessResources(org.apache.tools.ant.types.Resource stylesheet)
Styles all existing resources.

since
Ant 1.7

        Iterator iter = resources.iterator();
        while (iter.hasNext()) {
            Resource r = (Resource) iter.next();
            if (!r.isExists()) {
                continue;
            }
            File base = baseDir;
            String name = r.getName();
            if (r instanceof FileResource) {
                FileResource f = (FileResource) r;
                base = f.getBaseDir();
                if (base == null) {
                    name = f.getFile().getAbsolutePath();
                }
            }
            process(base, name, destDir, stylesheet);
        }
    
private voidresolveProcessor(java.lang.String proc)
Load processor here instead of in setProcessor - this will be called from within execute, so we have access to the latest classpath.

param
proc the name of the processor to load.
exception
Exception if the processor cannot be loaded.

        String classname;
        if (proc.equals(PROCESSOR_TRAX)) {
            classname = TRAX_LIAISON_CLASS;
        } else {
            //anything else is a classname
            classname = proc;
        }
        Class clazz = loadClass(classname);
        liaison = (XSLTLiaison) clazz.newInstance();
    
public voidsetBasedir(java.io.File dir)
Set the base directory; optional, default is the project's basedir.

param
dir the base directory

        baseDir = dir;
    
public voidsetClasspath(org.apache.tools.ant.types.Path classpath)
Set the optional classpath to the XSL processor

param
classpath the classpath to use when loading the XSL processor

        createClasspath().append(classpath);
    
public voidsetClasspathRef(org.apache.tools.ant.types.Reference r)
Set the reference to an optional classpath to the XSL processor

param
r the id of the Ant path instance to act as the classpath for loading the XSL processor

        createClasspath().setRefid(r);
    
public voidsetDestdir(java.io.File dir)
Set the destination directory into which the XSL result files should be copied to; required, unless in and out are specified.

param
dir the name of the destination directory

        destDir = dir;
    
public voidsetExtension(java.lang.String name)
Set the desired file extension to be used for the target; optional, default is html.

param
name the extension to use

        targetExtension = name;
    
public voidsetFileDirParameter(java.lang.String fileDirParameter)
Pass the directory name of the current processed file as a xsl parameter to the transformation. This value sets the name of that xsl parameter.

param
fileDirParameter name of the xsl parameter retrieving the current file directory

        this.fileDirParameter = fileDirParameter;
    
public voidsetFileNameParameter(java.lang.String fileNameParameter)
Pass the filename of the current processed file as a xsl parameter to the transformation. This value sets the name of that xsl parameter.

param
fileNameParameter name of the xsl parameter retrieving the current file name

        this.fileNameParameter = fileNameParameter;
    
public voidsetForce(boolean force)
Set whether to check dependencies, or always generate; optional, default is false.

param
force true if always generate.

        this.force = force;
    
public voidsetIn(java.io.File inFile)
specifies a single XML document to be styled. Should be used with the out attribute; ; required if out is set

param
inFile the input file

        this.inFile = inFile;
    
private voidsetLiaisonDynamicFileParameters(XSLTLiaison liaison, java.io.File inFile)
Sets file parameter(s) for directory and filename if the attribute 'filenameparameter' or 'filedirparameter' are set in the task.

param
liaison to change parameters for
param
inFile to get the additional file information from
throws
Exception if an exception occurs on filename lookup
since
Ant 1.7

        if (fileNameParameter != null) {
            liaison.addParam(fileNameParameter, inFile.getName());
        }
        if (fileDirParameter != null) {
            String fileName = FileUtils.getRelativePath(baseDir, inFile);
            File file = new File(fileName);
            // Give always a slash as file separator, so the stylesheet could be sure about that
            // Use '.' so a dir+"/"+name would not result in an absolute path
            liaison.addParam(
                fileDirParameter,
                (file.getParent() != null)
                ? file.getParent().replace('\\", '/") : ".");
        }
    
public voidsetOut(java.io.File outFile)
Specifies the output name for the styled result from the in attribute; required if in is set

param
outFile the output File instance.

        this.outFile = outFile;
    
public voidsetProcessor(java.lang.String processor)
Set the name of the XSL processor to use; optional, default trax. Other values are "xalan" for Xalan1

param
processor the name of the XSL processor

        this.processor = processor;
    
public voidsetReloadStylesheet(boolean b)
Controls whether the stylesheet is reloaded for every transform.

Setting this to true may get around a bug in certain Xalan-J versions, default is false.

param
b a boolean value
since
Ant 1.5.2

        reuseLoadedStylesheet = !b;
    
public voidsetScanIncludedDirectories(boolean b)
Whether to style all files in the included directories as well; optional, default is true.

param
b true if files in included directories are processed.
since
Ant 1.5

        performDirectoryScan = b;
    
public voidsetStyle(java.lang.String xslFile)
Name of the stylesheet to use - given either relative to the project's basedir or as an absolute path; required.

param
xslFile the stylesheet to use

        this.xslFile = xslFile;
    
public voidsetUseImplicitFileset(boolean useimplicitfileset)
Whether to use the implicit fileset.

Set this to false if you want explicit control with nested resource collections.

param
useimplicitfileset set to true if you want to use implicit fileset
since
Ant 1.7

        useImplicitFileset = useimplicitfileset;
    
public voidsetXslResource(org.apache.tools.ant.types.Resource xslResource)
API method to set the XSL Resource.

param
xslResource Resource to set as the stylesheet.
since
Ant 1.7

        this.xslResource = xslResource;