| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.tools.ant.taskdefs; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.EnumMap; |
| import java.util.Enumeration; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Vector; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.xpath.XPath; |
| import javax.xml.xpath.XPathConstants; |
| import javax.xml.xpath.XPathExpression; |
| import javax.xml.xpath.XPathExpressionException; |
| import javax.xml.xpath.XPathFactory; |
| import javax.xml.xpath.XPathVariableResolver; |
| |
| import org.apache.tools.ant.AntClassLoader; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.DirectoryScanner; |
| import org.apache.tools.ant.DynamicConfigurator; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.ProjectComponent; |
| import org.apache.tools.ant.PropertyHelper; |
| import org.apache.tools.ant.types.CommandlineJava; |
| import org.apache.tools.ant.types.Environment; |
| import org.apache.tools.ant.types.Mapper; |
| import org.apache.tools.ant.types.Path; |
| import org.apache.tools.ant.types.PropertySet; |
| import org.apache.tools.ant.types.Reference; |
| import org.apache.tools.ant.types.Resource; |
| import org.apache.tools.ant.types.ResourceCollection; |
| import org.apache.tools.ant.types.XMLCatalog; |
| import org.apache.tools.ant.types.resources.FileProvider; |
| import org.apache.tools.ant.types.resources.FileResource; |
| import org.apache.tools.ant.types.resources.Resources; |
| import org.apache.tools.ant.types.resources.Union; |
| import org.apache.tools.ant.util.ClasspathUtils; |
| import org.apache.tools.ant.util.FileNameMapper; |
| import org.apache.tools.ant.util.FileUtils; |
| import org.apache.tools.ant.util.ResourceUtils; |
| import org.apache.tools.ant.util.StringUtils; |
| |
| /** |
| * 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" |
| */ |
| |
| public class XSLTProcess extends MatchingTask implements XSLTLogger { |
| /** destination directory */ |
| private File destDir = null; |
| |
| /** where to find the source XML file, default is the project's basedir */ |
| private File baseDir = null; |
| |
| /** XSL stylesheet as a filename */ |
| private String xslFile = null; |
| |
| /** XSL stylesheet as a {@link org.apache.tools.ant.types.Resource} */ |
| private Resource xslResource = null; |
| |
| /** extension of the files produced by XSL processing */ |
| private String targetExtension = ".html"; |
| |
| /** name for XSL parameter containing the filename */ |
| private String fileNameParameter = null; |
| |
| /** name for XSL parameter containing the file directory */ |
| private String fileDirParameter = null; |
| |
| /** additional parameters to be passed to the stylesheets */ |
| private final List<Param> params = new ArrayList<Param>(); |
| |
| /** Input XML document to be used */ |
| private File inFile = null; |
| |
| /** Output file */ |
| private File outFile = null; |
| |
| /** The name of the XSL processor to use */ |
| private String processor; |
| |
| /** Classpath to use when trying to load the XSL processor */ |
| private Path classpath = null; |
| |
| /** The Liaison implementation to use to communicate with the XSL |
| * processor */ |
| private XSLTLiaison liaison; |
| |
| /** Flag which indicates if the stylesheet has been loaded into |
| * the processor */ |
| private boolean stylesheetLoaded = false; |
| |
| /** force output of target files even if they already exist */ |
| private boolean force = false; |
| |
| /** XSL output properties to be used */ |
| private final Vector outputProperties = new Vector(); |
| |
| /** for resolving entities such as dtds */ |
| private final XMLCatalog xmlCatalog = new XMLCatalog(); |
| |
| /** Utilities used for file operations */ |
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); |
| |
| /** |
| * Whether to style all files in the included directories as well. |
| * |
| * @since Ant 1.5 |
| */ |
| private boolean performDirectoryScan = true; |
| |
| /** |
| * factory element for TraX processors only |
| * @since Ant 1.6 |
| */ |
| private Factory factory = null; |
| |
| /** |
| * whether to reuse Transformer if transforming multiple files. |
| * @since 1.5.2 |
| */ |
| private boolean reuseLoadedStylesheet = true; |
| |
| /** |
| * AntClassLoader for the nested <classpath> - if set. |
| * |
| * <p>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).</p> |
| * |
| * @since Ant 1.6.2 |
| */ |
| private AntClassLoader loader = null; |
| |
| /** |
| * Mapper to use when a set of files gets processed. |
| * |
| * @since Ant 1.6.2 |
| */ |
| private Mapper mapperElement = null; |
| |
| /** |
| * Additional resource collections to process. |
| * |
| * @since Ant 1.7 |
| */ |
| private final Union resources = new Union(); |
| |
| /** |
| * Whether to use the implicit fileset. |
| * |
| * @since Ant 1.7 |
| */ |
| private boolean useImplicitFileset = true; |
| |
| /** |
| * The default processor is trax |
| * @since Ant 1.7 |
| */ |
| public static final String PROCESSOR_TRAX = "trax"; |
| |
| /** |
| * whether to suppress warnings. |
| * |
| * @since Ant 1.8.0 |
| */ |
| private boolean suppressWarnings = false; |
| |
| /** |
| * whether to fail the build if an error occurs during transformation. |
| * |
| * @since Ant 1.8.0 |
| */ |
| private boolean failOnTransformationError = true; |
| |
| /** |
| * whether to fail the build if an error occurs. |
| * |
| * @since Ant 1.8.0 |
| */ |
| private boolean failOnError = true; |
| |
| /** |
| * Whether the build should fail if the nested resource collection |
| * is empty. |
| * |
| * @since Ant 1.8.0 |
| */ |
| private boolean failOnNoResources = true; |
| |
| /** |
| * For evaluating template params |
| * |
| * @since Ant 1.9.3 |
| */ |
| private XPathFactory xpathFactory; |
| /** |
| * For evaluating template params |
| * |
| * @since Ant 1.9.3 |
| */ |
| private XPath xpath; |
| |
| /** |
| * System properties to set during transformation. |
| * |
| * @since Ant 1.8.0 |
| */ |
| private final CommandlineJava.SysProperties sysProperties = |
| new CommandlineJava.SysProperties(); |
| |
| /** |
| * Trace configuration for Xalan2. |
| * |
| * @since Ant 1.8.0 |
| */ |
| private TraceConfiguration traceConfiguration; |
| |
| /** |
| * Creates a new XSLTProcess Task. |
| */ |
| public XSLTProcess() { |
| } //-- XSLTProcess |
| |
| /** |
| * 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 |
| */ |
| public void setScanIncludedDirectories(final boolean b) { |
| performDirectoryScan = b; |
| } |
| |
| /** |
| * Controls whether the stylesheet is reloaded for every transform. |
| * |
| * <p>Setting this to true may get around a bug in certain |
| * Xalan-J versions, default is false.</p> |
| * @param b a <code>boolean</code> value |
| * @since Ant 1.5.2 |
| */ |
| public void setReloadStylesheet(final boolean b) { |
| reuseLoadedStylesheet = !b; |
| } |
| |
| /** |
| * 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 |
| */ |
| public void addMapper(final Mapper mapper) { |
| if (mapperElement != null) { |
| handleError("Cannot define more than one mapper"); |
| } else { |
| mapperElement = mapper; |
| } |
| } |
| |
| /** |
| * 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 |
| */ |
| public void add(final ResourceCollection rc) { |
| resources.add(rc); |
| } |
| |
| /** |
| * Add a nested <style> element. |
| * @param rc the configured Resources object represented as <style>. |
| * @since Ant 1.7 |
| */ |
| public void addConfiguredStyle(final Resources rc) { |
| if (rc.size() != 1) { |
| handleError("The style element must be specified with exactly one" |
| + " nested resource."); |
| } else { |
| setXslResource(rc.iterator().next()); |
| } |
| } |
| |
| /** |
| * API method to set the XSL Resource. |
| * @param xslResource Resource to set as the stylesheet. |
| * @since Ant 1.7 |
| */ |
| public void setXslResource(final Resource xslResource) { |
| this.xslResource = xslResource; |
| } |
| |
| /** |
| * Adds a nested filenamemapper. |
| * @param fileNameMapper the mapper to add |
| * @exception BuildException if more than one mapper is defined |
| * @since Ant 1.7.0 |
| */ |
| public void add(final FileNameMapper fileNameMapper) throws BuildException { |
| final Mapper mapper = new Mapper(getProject()); |
| mapper.add(fileNameMapper); |
| addMapper(mapper); |
| } |
| |
| /** |
| * Executes the task. |
| * |
| * @exception BuildException if there is an execution problem. |
| * @todo validate that if either in or out is defined, then both are |
| */ |
| @Override |
| public void execute() throws BuildException { |
| if ("style".equals(getTaskType())) { |
| log("Warning: the task name <style> is deprecated. Use <xslt> instead.", |
| Project.MSG_WARN); |
| } |
| final File savedBaseDir = baseDir; |
| |
| DirectoryScanner scanner; |
| String[] list; |
| String[] dirs; |
| |
| final String baseMessage = |
| "specify the stylesheet either as a filename in style attribute " |
| + "or as a nested resource"; |
| |
| if (xslResource == null && xslFile == null) { |
| handleError(baseMessage); |
| return; |
| } |
| if (xslResource != null && xslFile != null) { |
| handleError(baseMessage + " but not as both"); |
| return; |
| } |
| if (inFile != null && !inFile.exists()) { |
| handleError("input file " + inFile + " does not exist"); |
| return; |
| } |
| try { |
| setupLoader(); |
| |
| if (sysProperties.size() > 0) { |
| sysProperties.setSystem(); |
| } |
| |
| Resource styleResource; |
| if (baseDir == null) { |
| baseDir = getProject().getBaseDir(); |
| } |
| 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()) { |
| final File alternative = FILE_UTILS.resolveFile(baseDir, xslFile); |
| /* |
| * shouldn't throw out deprecation warnings before we know, |
| * the wrong version has been used. |
| */ |
| if (alternative.exists()) { |
| log("DEPRECATED - the 'style' attribute should be " |
| + "relative to the project's"); |
| log(" basedir, not the tasks's basedir."); |
| stylesheet = alternative; |
| } |
| } |
| final FileResource fr = new FileResource(); |
| fr.setProject(getProject()); |
| fr.setFile(stylesheet); |
| styleResource = fr; |
| } else { |
| styleResource = xslResource; |
| } |
| |
| if (!styleResource.isExists()) { |
| handleError("stylesheet " + styleResource + " doesn't exist."); |
| return; |
| } |
| |
| // if we have an in file and out then process them |
| if (inFile != null && outFile != null) { |
| process(inFile, outFile, styleResource); |
| 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, styleResource); |
| } |
| 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, |
| styleResource); |
| } |
| } |
| } |
| } else { // only resource collections, there better be some |
| if (resources.size() == 0) { |
| if (failOnNoResources) { |
| handleError("no resources specified"); |
| } |
| return; |
| } |
| } |
| processResources(styleResource); |
| } finally { |
| if (loader != null) { |
| loader.resetThreadContextLoader(); |
| loader.cleanup(); |
| loader = null; |
| } |
| if (sysProperties.size() > 0) { |
| sysProperties.restoreSystem(); |
| } |
| liaison = null; |
| stylesheetLoaded = false; |
| baseDir = savedBaseDir; |
| } |
| } |
| |
| /** |
| * Set whether to check dependencies, or always generate; |
| * optional, default is false. |
| * |
| * @param force true if always generate. |
| */ |
| public void setForce(final boolean force) { |
| this.force = force; |
| } |
| |
| /** |
| * Set the base directory; |
| * optional, default is the project's basedir. |
| * |
| * @param dir the base directory |
| **/ |
| public void setBasedir(final File dir) { |
| baseDir = dir; |
| } |
| |
| /** |
| * Set the destination directory into which the XSL result |
| * files should be copied to; |
| * required, unless <tt>in</tt> and <tt>out</tt> are |
| * specified. |
| * @param dir the name of the destination directory |
| **/ |
| public void setDestdir(final File dir) { |
| destDir = dir; |
| } |
| |
| /** |
| * Set the desired file extension to be used for the target; |
| * optional, default is html. |
| * @param name the extension to use |
| **/ |
| public void setExtension(final String name) { |
| targetExtension = name; |
| } |
| |
| /** |
| * 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 |
| */ |
| public void setStyle(final String xslFile) { |
| this.xslFile = xslFile; |
| } |
| |
| /** |
| * Set the optional classpath to the XSL processor |
| * |
| * @param classpath the classpath to use when loading the XSL processor |
| */ |
| public void setClasspath(final Path classpath) { |
| createClasspath().append(classpath); |
| } |
| |
| /** |
| * Set the optional classpath to the XSL processor |
| * |
| * @return a path instance to be configured by the Ant core. |
| */ |
| public Path createClasspath() { |
| if (classpath == null) { |
| classpath = new Path(getProject()); |
| } |
| return classpath.createPath(); |
| } |
| |
| /** |
| * 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 |
| */ |
| public void setClasspathRef(final Reference r) { |
| createClasspath().setRefid(r); |
| } |
| |
| /** |
| * Set the name of the XSL processor to use; optional, default trax. |
| * |
| * @param processor the name of the XSL processor |
| */ |
| public void setProcessor(final String processor) { |
| this.processor = processor; |
| } |
| |
| /** |
| * Whether to use the implicit fileset. |
| * |
| * <p>Set this to false if you want explicit control with nested |
| * resource collections.</p> |
| * @param useimplicitfileset set to true if you want to use implicit fileset |
| * @since Ant 1.7 |
| */ |
| public void setUseImplicitFileset(final boolean useimplicitfileset) { |
| useImplicitFileset = useimplicitfileset; |
| } |
| |
| /** |
| * Add the catalog to our internal catalog |
| * |
| * @param xmlCatalog the XMLCatalog instance to use to look up DTDs |
| */ |
| public void addConfiguredXMLCatalog(final XMLCatalog xmlCatalog) { |
| this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog); |
| } |
| |
| /** |
| * 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 |
| */ |
| public void setFileNameParameter(final String fileNameParameter) { |
| this.fileNameParameter = fileNameParameter; |
| } |
| |
| /** |
| * 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 |
| */ |
| public void setFileDirParameter(final String fileDirParameter) { |
| this.fileDirParameter = fileDirParameter; |
| } |
| |
| /** |
| * Whether to suppress warning messages of the processor. |
| * |
| * @param b boolean |
| * @since Ant 1.8.0 |
| */ |
| public void setSuppressWarnings(final boolean b) { |
| suppressWarnings = b; |
| } |
| |
| /** |
| * Whether to suppress warning messages of the processor. |
| * |
| * @return boolean |
| * @since Ant 1.8.0 |
| */ |
| public boolean getSuppressWarnings() { |
| return suppressWarnings; |
| } |
| |
| /** |
| * Whether transformation errors should make the build fail. |
| * |
| * @param b boolean |
| * @since Ant 1.8.0 |
| */ |
| public void setFailOnTransformationError(final boolean b) { |
| failOnTransformationError = b; |
| } |
| |
| /** |
| * Whether any errors should make the build fail. |
| * |
| * @param b boolean |
| * @since Ant 1.8.0 |
| */ |
| public void setFailOnError(final boolean b) { |
| failOnError = b; |
| } |
| |
| /** |
| * Whether the build should fail if the nested resource collection is empty. |
| * |
| * @param b boolean |
| * @since Ant 1.8.0 |
| */ |
| public void setFailOnNoResources(final boolean b) { |
| failOnNoResources = b; |
| } |
| |
| /** |
| * A system property to set during transformation. |
| * |
| * @param sysp Environment.Variable |
| * @since Ant 1.8.0 |
| */ |
| public void addSysproperty(final Environment.Variable sysp) { |
| sysProperties.addVariable(sysp); |
| } |
| |
| /** |
| * A set of system properties to set during transformation. |
| * |
| * @param sysp PropertySet |
| * @since Ant 1.8.0 |
| */ |
| public void addSyspropertyset(final PropertySet sysp) { |
| sysProperties.addSyspropertyset(sysp); |
| } |
| |
| /** |
| * Enables Xalan2 traces and uses the given configuration. |
| * |
| * <p>Note that this element doesn't have any effect with a |
| * processor other than trax or if the Transformer is not Xalan2's |
| * transformer implementation.</p> |
| * |
| * @return TraceConfiguration |
| * @since Ant 1.8.0 |
| */ |
| public TraceConfiguration createTrace() { |
| if (traceConfiguration != null) { |
| throw new BuildException("can't have more than one trace" |
| + " configuration"); |
| } |
| traceConfiguration = new TraceConfiguration(); |
| return traceConfiguration; |
| } |
| |
| /** |
| * Configuration for Xalan2 traces. |
| * |
| * @return TraceConfiguration |
| * @since Ant 1.8.0 |
| */ |
| public TraceConfiguration getTraceConfiguration() { |
| return traceConfiguration; |
| } |
| |
| /** |
| * 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. |
| */ |
| private void resolveProcessor(final String proc) throws Exception { |
| if (proc.equals(PROCESSOR_TRAX)) { |
| liaison = new org.apache.tools.ant.taskdefs.optional.TraXLiaison(); |
| } else { |
| //anything else is a classname |
| final Class clazz = loadClass(proc); |
| liaison = (XSLTLiaison) clazz.newInstance(); |
| } |
| } |
| |
| /** |
| * 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. |
| */ |
| private Class loadClass(final String classname) throws ClassNotFoundException { |
| setupLoader(); |
| if (loader == null) { |
| return Class.forName(classname); |
| } |
| return Class.forName(classname, true, loader); |
| } |
| |
| /** |
| * If a custom classpath has been defined but no loader created |
| * yet, create the classloader and set it as the context |
| * classloader. |
| */ |
| private void setupLoader() { |
| if (classpath != null && loader == null) { |
| loader = getProject().createClassLoader(classpath); |
| loader.setThreadContextLoader(); |
| } |
| } |
| |
| /** |
| * Specifies the output name for the styled result from the |
| * <tt>in</tt> attribute; required if <tt>in</tt> is set |
| * |
| * @param outFile the output File instance. |
| */ |
| public void setOut(final File outFile) { |
| this.outFile = outFile; |
| } |
| |
| /** |
| * specifies a single XML document to be styled. Should be used |
| * with the <tt>out</tt> attribute; required if <tt>out</tt> is set |
| * |
| * @param inFile the input file |
| */ |
| public void setIn(final File inFile) { |
| this.inFile = inFile; |
| } |
| |
| /** |
| * Throws a BuildException if the destination directory hasn't |
| * been specified. |
| * @since Ant 1.7 |
| */ |
| private void checkDest() { |
| if (destDir == null) { |
| handleError("destdir attributes must be set!"); |
| } |
| } |
| |
| /** |
| * Styles all existing resources. |
| * |
| * @param stylesheet style sheet to use |
| * @since Ant 1.7 |
| */ |
| private void processResources(final Resource stylesheet) { |
| for (final Resource r : resources) { |
| if (!r.isExists()) { |
| continue; |
| } |
| File base = baseDir; |
| String name = r.getName(); |
| final FileProvider fp = r.as(FileProvider.class); |
| if (fp != null) { |
| final FileResource f = ResourceUtils.asFileResource(fp); |
| base = f.getBaseDir(); |
| if (base == null) { |
| name = f.getFile().getAbsolutePath(); |
| } |
| } |
| process(base, name, destDir, 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. |
| */ |
| private void process(final File baseDir, final String xmlFile, final File destDir, final Resource stylesheet) |
| throws BuildException { |
| |
| File outF = null; |
| File inF = null; |
| |
| try { |
| final 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(); |
| } |
| |
| final 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.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 (final 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(); |
| } |
| handleTransformationError(ex); |
| } |
| |
| } //-- processXML |
| |
| /** |
| * 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. |
| */ |
| private void process(final File inFile, final File outFile, final Resource stylesheet) throws BuildException { |
| try { |
| final 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 (final Exception ex) { |
| log("Failed to process " + inFile, Project.MSG_INFO); |
| if (outFile != null) { |
| outFile.delete(); |
| } |
| handleTransformationError(ex); |
| } |
| } |
| |
| /** |
| * 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. |
| */ |
| private void ensureDirectoryFor(final File targetFile) throws BuildException { |
| final File directory = targetFile.getParentFile(); |
| if (!directory.exists()) { |
| if (!(directory.mkdirs() || directory.isDirectory())) { |
| handleError("Unable to create directory: " |
| + directory.getAbsolutePath()); |
| } |
| } |
| } |
| |
| /** |
| * Get the factory instance configured for this processor |
| * |
| * @return the factory instance in use |
| */ |
| public Factory getFactory() { |
| return factory; |
| } |
| |
| /** |
| * Get the XML catalog containing entity definitions |
| * |
| * @return the XML catalog for the task. |
| */ |
| public XMLCatalog getXMLCatalog() { |
| xmlCatalog.setProject(getProject()); |
| return xmlCatalog; |
| } |
| |
| /** |
| * Get an enumeration on the outputproperties. |
| * @return the outputproperties |
| */ |
| public Enumeration getOutputProperties() { |
| return outputProperties.elements(); |
| } |
| |
| /** |
| * Get the Liaison implementation to use in processing. |
| * |
| * @return an instance of the XSLTLiaison interface. |
| */ |
| protected XSLTLiaison getLiaison() { |
| // if processor wasn't specified, use TraX. |
| if (liaison == null) { |
| if (processor != null) { |
| try { |
| resolveProcessor(processor); |
| } catch (final Exception e) { |
| handleError(e); |
| } |
| } else { |
| try { |
| resolveProcessor(PROCESSOR_TRAX); |
| } catch (final Throwable e1) { |
| log(StringUtils.getStackTrace(e1), Project.MSG_ERR); |
| handleError(e1); |
| } |
| } |
| } |
| return liaison; |
| } |
| |
| /** |
| * Create an instance of an XSL parameter for configuration by Ant. |
| * |
| * @return an instance of the Param class to be configured. |
| */ |
| public Param createParam() { |
| final Param p = new Param(); |
| params.add(p); |
| return p; |
| } |
| |
| /** |
| * The Param inner class used to store XSL parameters |
| */ |
| public static class Param { |
| /** The parameter name */ |
| private String name = null; |
| |
| /** The parameter's value */ |
| private String expression = null; |
| |
| /** |
| * Type of the expression. |
| * @see ParamType |
| */ |
| private String type; |
| |
| private Object ifCond; |
| private Object unlessCond; |
| private Project project; |
| |
| /** |
| * Set the current project |
| * |
| * @param project the current project |
| */ |
| public void setProject(final Project project) { |
| this.project = project; |
| } |
| |
| /** |
| * Set the parameter name. |
| * |
| * @param name the name of the parameter. |
| */ |
| public void setName(final String name) { |
| this.name = name; |
| } |
| |
| /** |
| * The parameter value - |
| * can be a primitive type value or an XPath expression. |
| * @param expression the parameter's value/expression. |
| * @see #setType(java.lang.String) |
| */ |
| public void setExpression(final String expression) { |
| this.expression = expression; |
| } |
| |
| /** |
| * @param type String |
| * @see ParamType |
| * @since Ant 1.9.3 |
| */ |
| public void setType(final String type) { |
| this.type = type; |
| } |
| |
| /** |
| * Get the parameter name |
| * |
| * @return the parameter name |
| * @exception BuildException if the name is not set. |
| */ |
| public String getName() throws BuildException { |
| if (name == null) { |
| throw new BuildException("Name attribute is missing."); |
| } |
| return name; |
| } |
| |
| /** |
| * Get the parameter's value |
| * |
| * @return the parameter value |
| * @exception BuildException if the value is not set. |
| * @see #getType() |
| */ |
| public String getExpression() throws BuildException { |
| if (expression == null) { |
| throw new BuildException("Expression attribute is missing."); |
| } |
| return expression; |
| } |
| |
| /** |
| * @return String |
| * @see ParamType |
| * @since Ant 1.9.3 |
| */ |
| public String getType() { |
| return type; |
| } |
| |
| /** |
| * Set whether this param should be used. It will be used if |
| * the expression evaluates to true or the name of a property |
| * which has been set, otherwise it won't. |
| * @param ifCond evaluated expression |
| * @since Ant 1.8.0 |
| */ |
| public void setIf(final Object ifCond) { |
| this.ifCond = ifCond; |
| } |
| |
| /** |
| * Set whether this param should be used. It will be used if |
| * the expression evaluates to true or the name of a property |
| * which has been set, otherwise it won't. |
| * @param ifProperty evaluated expression |
| */ |
| public void setIf(final String ifProperty) { |
| setIf((Object) ifProperty); |
| } |
| |
| /** |
| * Set whether this param should NOT be used. It will not be |
| * used if the expression evaluates to true or the name of a |
| * property which has been set, otherwise it will be used. |
| * @param unlessCond evaluated expression |
| * @since Ant 1.8.0 |
| */ |
| public void setUnless(final Object unlessCond) { |
| this.unlessCond = unlessCond; |
| } |
| |
| /** |
| * Set whether this param should NOT be used. It will not be |
| * used if the expression evaluates to true or the name of a |
| * property which has been set, otherwise it will be used. |
| * @param unlessProperty evaluated expression |
| */ |
| public void setUnless(final String unlessProperty) { |
| setUnless((Object) unlessProperty); |
| } |
| |
| /** |
| * Ensures that the param passes the conditions placed |
| * on it with <code>if</code> and <code>unless</code> properties. |
| * @return true if the task passes the "if" and "unless" parameters |
| */ |
| public boolean shouldUse() { |
| final PropertyHelper ph = PropertyHelper.getPropertyHelper(project); |
| return ph.testIfCondition(ifCond) |
| && ph.testUnlessCondition(unlessCond); |
| } |
| } // Param |
| |
| /** |
| * Enum for types of the parameter expression. |
| * |
| * <p>The expression can be:</p> |
| * <ul> |
| * <li>primitive type that will be parsed from the string value e.g. |
| * {@linkplain Integer#parseInt(java.lang.String)}</li> |
| * <li>XPath expression that will be evaluated (outside of the transformed |
| * document - on empty one) and casted to given type. Inside XPath |
| * expressions the Ant variables (properties) can be used (as XPath |
| * variables - e.g. $variable123). n.b. placeholders in form of |
| * ${variable123} will be substituted with their values before evaluating the |
| * XPath expression (so it can be used for dynamic XPath function names and |
| * other hacks).</li> |
| * </ul> |
| * <p>The parameter will be then passed to the XSLT template.</p> |
| * |
| * <p>Default type (if omitted) is primitive String. So if the expression is e.g |
| * "true" with no type, in XSLT it will be only a text string, not true |
| * boolean.</p> |
| * |
| * @see Param#setType(java.lang.String) |
| * @see Param#setExpression(java.lang.String) |
| * @since Ant 1.9.3 |
| */ |
| public enum ParamType { |
| |
| STRING, |
| BOOLEAN, |
| INT, |
| LONG, |
| DOUBLE, |
| XPATH_STRING, |
| XPATH_BOOLEAN, |
| XPATH_NUMBER, |
| XPATH_NODE, |
| XPATH_NODESET; |
| |
| public static final Map<ParamType, QName> XPATH_TYPES; |
| |
| static { |
| final Map<ParamType, QName> m = new EnumMap<ParamType, QName>(ParamType.class); |
| m.put(XPATH_STRING, XPathConstants.STRING); |
| m.put(XPATH_BOOLEAN, XPathConstants.BOOLEAN); |
| m.put(XPATH_NUMBER, XPathConstants.NUMBER); |
| m.put(XPATH_NODE, XPathConstants.NODE); |
| m.put(XPATH_NODESET, XPathConstants.NODESET); |
| XPATH_TYPES = Collections.unmodifiableMap(m); |
| } |
| } |
| |
| /** |
| * Create an instance of an output property to be configured. |
| * @return the newly created output property. |
| * @since Ant 1.5 |
| */ |
| public OutputProperty createOutputProperty() { |
| final OutputProperty p = new OutputProperty(); |
| outputProperties.addElement(p); |
| return p; |
| } |
| |
| /** |
| * Specify how the result tree should be output as specified |
| * in the <a href="http://www.w3.org/TR/xslt#output"> |
| * specification</a>. |
| * @since Ant 1.5 |
| */ |
| public static class OutputProperty { |
| /** output property name */ |
| private String name; |
| |
| /** output property value */ |
| private String value; |
| |
| /** |
| * @return the output property name. |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * set the name for this property |
| * @param name A non-null String that specifies an |
| * output property name, which may be namespace qualified. |
| */ |
| public void setName(final String name) { |
| this.name = name; |
| } |
| |
| /** |
| * @return the output property value. |
| */ |
| public String getValue() { |
| return value; |
| } |
| |
| /** |
| * set the value for this property |
| * @param value The non-null string value of the output property. |
| */ |
| public void setValue(final String value) { |
| this.value = value; |
| } |
| } |
| |
| /** |
| * Initialize internal instance of XMLCatalog. |
| * Initialize XPath for parameter evaluation. |
| * @throws BuildException on error |
| */ |
| @Override |
| public void init() throws BuildException { |
| super.init(); |
| xmlCatalog.setProject(getProject()); |
| |
| xpathFactory = XPathFactory.newInstance(); |
| xpath = xpathFactory.newXPath(); |
| xpath.setXPathVariableResolver(new XPathVariableResolver() { |
| public Object resolveVariable(final QName variableName) { |
| return getProject().getProperty(variableName.toString()); |
| } |
| }); |
| } |
| |
| /** |
| * 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 |
| */ |
| @Deprecated |
| protected void configureLiaison(final File stylesheet) throws BuildException { |
| final FileResource fr = new FileResource(); |
| fr.setProject(getProject()); |
| fr.setFile(stylesheet); |
| configureLiaison(fr); |
| } |
| |
| /** |
| * 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 |
| */ |
| protected void configureLiaison(final Resource stylesheet) throws BuildException { |
| if (stylesheetLoaded && reuseLoadedStylesheet) { |
| return; |
| } |
| stylesheetLoaded = true; |
| |
| try { |
| log("Loading stylesheet " + stylesheet, Project.MSG_INFO); |
| // We call liaison.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 |
| final FileProvider fp = |
| stylesheet.as(FileProvider.class); |
| if (fp != null) { |
| liaison.setStylesheet(fp.getFile()); |
| } else { |
| handleError(liaison.getClass().toString() |
| + " accepts the stylesheet only as a file"); |
| return; |
| } |
| } |
| for (final Param p : params) { |
| if (p.shouldUse()) { |
| final Object evaluatedParam = evaluateParam(p); |
| if (liaison instanceof XSLTLiaison4) { |
| ((XSLTLiaison4) liaison).addParam(p.getName(), evaluatedParam); |
| } else { |
| if (evaluatedParam == null || evaluatedParam instanceof String) { |
| liaison.addParam(p.getName(), (String) evaluatedParam); |
| } else { |
| log("XSLTLiaison '" + liaison.getClass().getName() |
| + "' supports only String parameters. Converting parameter '" + p.getName() |
| + "' to its String value '" + evaluatedParam, Project.MSG_WARN); |
| liaison.addParam(p.getName(), String.valueOf(evaluatedParam)); |
| } |
| } |
| } |
| } |
| } catch (final Exception ex) { |
| log("Failed to transform using stylesheet " + stylesheet, Project.MSG_INFO); |
| handleTransformationError(ex); |
| } |
| } |
| |
| /** |
| * Evaluates parameter expression according to its type. |
| * |
| * @param param parameter from Ant build file |
| * @return value to be passed to XSLT as parameter |
| * @throws IllegalArgumentException if param type is unsupported |
| * @throws NumberFormatException if expression of numeric type is not |
| * desired numeric type |
| * @throws XPathExpressionException if XPath expression can not be compiled |
| * @since Ant 1.9.3 |
| */ |
| private Object evaluateParam(final Param param) throws XPathExpressionException { |
| final String typeName = param.getType(); |
| final String expression = param.getExpression(); |
| |
| ParamType type; |
| |
| if (typeName == null || "".equals(typeName)) { |
| type = ParamType.STRING; // String is default |
| } else { |
| try { |
| type = ParamType.valueOf(typeName); |
| } catch (final IllegalArgumentException e) { |
| throw new IllegalArgumentException("Invalid XSLT parameter type: " + typeName, e); |
| } |
| } |
| |
| switch (type) { |
| case STRING: |
| return expression; |
| case BOOLEAN: |
| return Boolean.parseBoolean(expression); |
| case DOUBLE: |
| return Double.parseDouble(expression); |
| case INT: |
| return Integer.parseInt(expression); |
| case LONG: |
| return Long.parseLong(expression); |
| default: // XPath expression |
| final QName xpathType = ParamType.XPATH_TYPES.get(type); |
| if (xpathType == null) { |
| throw new IllegalArgumentException("Invalid XSLT parameter type: " + typeName); |
| } else { |
| final XPathExpression xpe = xpath.compile(expression); |
| // null = evaluate XPath on empty XML document |
| return xpe.evaluate((Object) null, xpathType); |
| } |
| } |
| } |
| |
| /** |
| * 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 |
| */ |
| private void setLiaisonDynamicFileParameters( |
| final XSLTLiaison liaison, final File inFile) throws Exception { //NOSONAR |
| if (fileNameParameter != null) { |
| liaison.addParam(fileNameParameter, inFile.getName()); |
| } |
| if (fileDirParameter != null) { |
| final String fileName = FileUtils.getRelativePath(baseDir, inFile); |
| final 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( |
| '\\', '/') : "."); |
| } |
| } |
| |
| /** |
| * 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. |
| */ |
| public Factory createFactory() throws BuildException { |
| if (factory != null) { |
| handleError("'factory' element must be unique"); |
| } else { |
| factory = new Factory(); |
| } |
| return factory; |
| } |
| |
| /** |
| * Throws an exception with the given message if failOnError is |
| * true, otherwise logs the message using the WARN level. |
| * |
| * @param msg String |
| * @since Ant 1.8.0 |
| */ |
| protected void handleError(final String msg) { |
| if (failOnError) { |
| throw new BuildException(msg, getLocation()); |
| } |
| log(msg, Project.MSG_WARN); |
| } |
| |
| |
| /** |
| * Throws an exception with the given nested exception if |
| * failOnError is true, otherwise logs the message using the WARN |
| * level. |
| * |
| * @param ex Throwable |
| * @since Ant 1.8.0 |
| */ |
| protected void handleError(final Throwable ex) { |
| if (failOnError) { |
| throw new BuildException(ex); |
| } else { |
| log("Caught an exception: " + ex, Project.MSG_WARN); |
| } |
| } |
| |
| /** |
| * Throws an exception with the given nested exception if |
| * failOnError and failOnTransformationError are true, otherwise |
| * logs the message using the WARN level. |
| * |
| * @param ex Exception |
| * @since Ant 1.8.0 |
| */ |
| protected void handleTransformationError(final Exception ex) { |
| if (failOnError && failOnTransformationError) { |
| throw new BuildException(ex); |
| } else { |
| log("Caught an error during transformation: " + ex, |
| Project.MSG_WARN); |
| } |
| } |
| |
| /** |
| * The factory element to configure a transformer factory |
| * @since Ant 1.6 |
| */ |
| public static class Factory { |
| |
| /** the factory class name to use for TraXLiaison */ |
| private String name; |
| |
| /** |
| * the list of factory attributes to use for TraXLiaison |
| */ |
| private final List<Attribute> attributes = new ArrayList<Attribute>(); |
| |
| /** |
| * the list of factory features to use for TraXLiaison |
| */ |
| private final List<Feature> features = new ArrayList<Feature>(); |
| |
| /** |
| * @return the name of the factory. |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * Set the name of the factory |
| * @param name the name of the factory. |
| */ |
| public void setName(final String name) { |
| this.name = name; |
| } |
| |
| /** |
| * Create an instance of a factory attribute. |
| * @param attr the newly created factory attribute |
| */ |
| public void addAttribute(final Attribute attr) { |
| attributes.add(attr); |
| } |
| |
| /** |
| * return the attribute elements. |
| * @return the enumeration of attributes |
| */ |
| public Enumeration getAttributes() { |
| return Collections.enumeration(attributes); |
| } |
| |
| /** |
| * Create an instance of a factory feature. |
| * @param feature the newly created feature |
| * @since Ant 1.9.8 |
| */ |
| public void addFeature(final Feature feature) { |
| features.add(feature); |
| } |
| |
| /** |
| * The configured features. |
| * @since Ant 1.9.8 |
| * |
| * @return Iterable<Feature> |
| */ |
| public Iterable<Feature> getFeatures() { |
| return features; |
| } |
| |
| /** |
| * A JAXP factory attribute. This is mostly processor specific, for |
| * example for Xalan 2.3+, the following attributes could be set: |
| * <ul> |
| * <li>http://xml.apache.org/xalan/features/optimize (true|false) </li> |
| * <li>http://xml.apache.org/xalan/features/incremental (true|false) </li> |
| * </ul> |
| */ |
| public static class Attribute |
| extends ProjectComponent |
| implements DynamicConfigurator { |
| |
| /** attribute name, mostly processor specific */ |
| private String name; |
| |
| /** attribute value, often a boolean string */ |
| private Object value; |
| |
| /** |
| * @return the attribute name. |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * @return the attribute value. |
| */ |
| public Object getValue() { |
| return value; |
| } |
| |
| /** |
| * Not used. |
| * @param name not used |
| * @return null |
| * @throws BuildException never |
| */ |
| public Object createDynamicElement(final String name) throws BuildException { |
| return null; |
| } |
| |
| /** |
| * Set an attribute. |
| * Only "name" and "value" are supported as names. |
| * @param name the name of the attribute |
| * @param value the value of the attribute |
| * @throws BuildException on error |
| */ |
| public void setDynamicAttribute(final String name, final String value) throws BuildException { |
| // only 'name' and 'value' exist. |
| if ("name".equalsIgnoreCase(name)) { |
| this.name = value; |
| } else if ("value".equalsIgnoreCase(name)) { |
| // a value must be of a given type |
| // say boolean|integer|string that are mostly used. |
| if ("true".equalsIgnoreCase(value)) { |
| this.value = Boolean.TRUE; |
| } else if ("false".equalsIgnoreCase(value)) { |
| this.value = Boolean.FALSE; |
| } else { |
| try { |
| this.value = new Integer(value); |
| } catch (final NumberFormatException e) { |
| this.value = value; |
| } |
| } |
| } else if ("valueref".equalsIgnoreCase(name)) { |
| this.value = getProject().getReference(value); |
| } else if ("classloaderforpath".equalsIgnoreCase(name)) { |
| this.value = |
| ClasspathUtils.getClassLoaderForPath(getProject(), |
| new Reference(getProject(), |
| value)); |
| } else { |
| throw new BuildException("Unsupported attribute: " + name); |
| } |
| } |
| } // -- class Attribute |
| |
| /** |
| * A feature for the TraX factory. |
| * @since Ant 1.9.8 |
| */ |
| public static class Feature { |
| private String name; |
| private boolean value; |
| |
| public Feature() { } |
| public Feature(String name, boolean value) { |
| this.name = name; |
| this.value = value; |
| } |
| |
| /** |
| * @param name the feature name. |
| */ |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| /** |
| * @param value the feature value. |
| */ |
| public void setValue(boolean value) { |
| this.value = value; |
| } |
| |
| /** |
| * @return the feature name. |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * @return the feature value. |
| */ |
| public boolean getValue() { |
| return value; |
| } |
| } |
| } // -- class Factory |
| |
| /** |
| * Mapper implementation of the "traditional" way <xslt> |
| * mapped filenames. |
| * |
| * <p>If the file has an extension, chop it off. Append whatever |
| * the user has specified as extension or ".html".</p> |
| * |
| * @since Ant 1.6.2 |
| */ |
| private class StyleMapper implements FileNameMapper { |
| public void setFrom(final String from) { |
| } |
| public void setTo(final String to) { |
| } |
| public String[] mapFileName(String xmlFile) { |
| final int dotPos = xmlFile.lastIndexOf('.'); |
| if (dotPos > 0) { |
| xmlFile = xmlFile.substring(0, dotPos); |
| } |
| return new String[] {xmlFile + targetExtension}; |
| } |
| } |
| |
| /** |
| * Configuration for Xalan2 traces. |
| * |
| * @since Ant 1.8.0 |
| */ |
| public final class TraceConfiguration { |
| private boolean elements, extension, generation, selection, templates; |
| |
| /** |
| * Set to true if the listener is to print events that occur |
| * as each node is 'executed' in the stylesheet. |
| * |
| * @param b boolean |
| */ |
| public void setElements(final boolean b) { |
| elements = b; |
| } |
| |
| /** |
| * True if the listener is to print events that occur as each |
| * node is 'executed' in the stylesheet. |
| * |
| * @return boolean |
| */ |
| public boolean getElements() { |
| return elements; |
| } |
| |
| /** |
| * Set to true if the listener is to print information after |
| * each extension event. |
| * |
| * @param b boolean |
| */ |
| public void setExtension(final boolean b) { |
| extension = b; |
| } |
| |
| /** |
| * True if the listener is to print information after each |
| * extension event. |
| * |
| * @return boolean |
| */ |
| public boolean getExtension() { |
| return extension; |
| } |
| |
| /** |
| * Set to true if the listener is to print information after |
| * each result-tree generation event. |
| * |
| * @param b boolean |
| */ |
| public void setGeneration(final boolean b) { |
| generation = b; |
| } |
| |
| /** |
| * True if the listener is to print information after each |
| * result-tree generation event. |
| * |
| * @return boolean |
| */ |
| public boolean getGeneration() { |
| return generation; |
| } |
| |
| /** |
| * Set to true if the listener is to print information after |
| * each selection event. |
| * |
| * @param b boolean |
| */ |
| public void setSelection(final boolean b) { |
| selection = b; |
| } |
| |
| /** |
| * True if the listener is to print information after each |
| * selection event. |
| * |
| * @return boolean |
| */ |
| public boolean getSelection() { |
| return selection; |
| } |
| |
| /** |
| * Set to true if the listener is to print an event whenever a |
| * template is invoked. |
| * |
| * @param b boolean |
| */ |
| public void setTemplates(final boolean b) { |
| templates = b; |
| } |
| |
| /** |
| * True if the listener is to print an event whenever a |
| * template is invoked. |
| * |
| * @return boolean |
| */ |
| public boolean getTemplates() { |
| return templates; |
| } |
| |
| /** |
| * The stream to write traces to. |
| * |
| * @return OutputStream |
| */ |
| public java.io.OutputStream getOutputStream() { |
| return new LogOutputStream(XSLTProcess.this); |
| } |
| } |
| |
| } |