diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 45c04e1eb..a3de7235e 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -239,6 +239,7 @@ Tom Cunningham Tom Dimock Tom Eugelink Ulrich Schmidt +Victor Toni Waldek Herka Will Wang William Ferguson diff --git a/contributors.xml b/contributors.xml index 24ae73a23..e5ecb2516 100644 --- a/contributors.xml +++ b/contributors.xml @@ -950,6 +950,10 @@ Ulrich Schmidt + + Victor + Toni + Will Wang diff --git a/docs/manual/CoreTasks/style.html b/docs/manual/CoreTasks/style.html index 6d823e320..307419721 100644 --- a/docs/manual/CoreTasks/style.html +++ b/docs/manual/CoreTasks/style.html @@ -16,7 +16,7 @@ or for generating code.

Note: If you are using JDK 1.4 or higher, this task does not require external libraries not supplied in the Ant distribution. However, often the built in XSL engine is not as up -to date as a fresh download, so an update is still highly recommended. +to date as a fresh download, so an update is still highly recommended. See Library Dependencies for more information.

It is possible to refine the set of files that are being processed. This can be done with the includes, includesfile, excludes, excludesfile and defaultexcludes @@ -189,6 +189,22 @@ element which is used to perform Entity and URI resolution.

Since Ant 1.7. No + + filenameparameter + Specifies a xsl parameter for accessing the name + of the current processed file. If not set, the file name is not + passed to the transformation. + Since Ant 1.7. + No + + + filedirparameter + Specifies a xsl parameter for accessing the directory + of the current processed file. If not set, the directory is not + passed to the transformation. + Since Ant 1.7. + No +

Parameters specified as nested elements

@@ -312,7 +328,7 @@ And in Saxon 7.x:
  • http://saxon.sf.net/feature/linenumbering (integer)
  • ...
  • -
    +

    Parameters

    @@ -417,10 +433,33 @@ See resources to see the concrete synt <param name="set" expression="value"/> </xslt> +

    Print the current processed file name

    +
    +<project>
    +  <xslt style="printFilename.xsl" destdir="out" basedir="in" extension=".txt"
    +        filenameparameter="filename"
    +        filedirparameter="filedir"
    +  />
    +</project>
    +
    +<xsl:stylesheet
    +  version="1.0"
    +  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    +
    +    <xsl:param name="filename"></xsl:param>
    +    <xsl:param name="filedir">.</xsl:param>
    +
    +<xsl:template match="/">
    +  Current file is <xsl:value-of select="$filename"/> in directory <xsl:value-of select="$filedir"/>.
    +</xsl:template>
    +
    +</xsl:stylesheet>
    +
    +

    Copyright © 2000-2006 The Apache Software Foundation. All rights Reserved.

    - + \ No newline at end of file diff --git a/src/etc/testcases/taskdefs/style/build.xml b/src/etc/testcases/taskdefs/style/build.xml index d92a73dec..e767feb14 100644 --- a/src/etc/testcases/taskdefs/style/build.xml +++ b/src/etc/testcases/taskdefs/style/build.xml @@ -11,6 +11,7 @@ + @@ -128,5 +129,55 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/etc/testcases/taskdefs/style/printFilename.xsl b/src/etc/testcases/taskdefs/style/printFilename.xsl new file mode 100644 index 000000000..e80642d89 --- /dev/null +++ b/src/etc/testcases/taskdefs/style/printFilename.xsl @@ -0,0 +1,22 @@ + + + + + + + + -not-set- + -not-set- + + + + filename='' + filedir ='' + + + + + + \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java index 38d509130..dff574c90 100644 --- a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java +++ b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java @@ -63,6 +63,12 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger { /** 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 */ + public String fileDirParameter = null; + /** additional parameters to be passed to the stylesheets */ private Vector params = new Vector(); @@ -472,6 +478,28 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger { 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(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(String fileDirParameter) { + this.fileDirParameter = fileDirParameter; + } + /** * Load processor here instead of in setProcessor - this will be * called from within execute, so we have access to the latest @@ -623,6 +651,7 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger { log("Processing " + inF + " to " + outF); configureLiaison(stylesheet); + setLiaisonDynamicFileParameters(liaison, inF); liaison.transform(inF, outF); } } catch (Exception ex) { @@ -662,6 +691,7 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger { log("Processing " + inFile + " to " + outFile, Project.MSG_INFO); configureLiaison(stylesheet); + setLiaisonDynamicFileParameters(liaison, inFile); liaison.transform(inFile, outFile); } else { log("Skipping input file " + inFile @@ -721,7 +751,6 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger { return outputProperties.elements(); } - /** * Get the Liason implementation to use in processing. * @@ -993,6 +1022,31 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger { } } + /** + * 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( + XSLTLiaison liaison, + File inFile + ) throws Exception { + String fileName = FileUtils.getRelativePath(baseDir, inFile); + File file = new File(fileName); + + if (fileNameParameter != null) { + liaison.addParam(fileNameParameter, inFile.getName()); + } + if (fileDirParameter != null) { + liaison.addParam(fileDirParameter, (file.getParent()!=null) ? file.getParent() : "" ); + } + } + /** * Create the factory element to configure a trax liaison. * @return the newly created factory element. @@ -1148,4 +1202,4 @@ public class XSLTProcess extends MatchingTask implements XSLTLogger { } } -} +} \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java b/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java index e5a1df852..0e08478a7 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java @@ -25,6 +25,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Hashtable; import java.util.Vector; import java.util.Enumeration; import java.net.URL; @@ -114,7 +115,7 @@ public class TraXLiaison implements XSLTLiaison3, ErrorListener, XSLTLoggerAware private Vector outputProperties = new Vector(); /** stylesheet parameters */ - private Vector params = new Vector(); + private Hashtable params = new Hashtable(); /** factory attributes */ private Vector attributes = new Vector(); @@ -177,6 +178,11 @@ public class TraXLiaison implements XSLTLiaison3, ErrorListener, XSLTLoggerAware // not sure what could be the need of this... res.setSystemId(JAXPUtils.getSystemId(outfile)); Source src = getSource(fis, infile); + + // set parameters on each transformation, maybe something has changed + //(e.g. value of file name parameter) + setTransformationParameters(); + transformer.transform(src, res); } finally { // make sure to close all handles, otherwise the garbage @@ -320,16 +326,23 @@ public class TraXLiaison implements XSLTLiaison3, ErrorListener, XSLTLoggerAware if (uriResolver != null) { transformer.setURIResolver(uriResolver); } - for (int i = 0; i < params.size(); i++) { - final String[] pair = (String[]) params.elementAt(i); - transformer.setParameter(pair[0], pair[1]); - } for (int i = 0; i < outputProperties.size(); i++) { final String[] pair = (String[]) outputProperties.elementAt(i); transformer.setOutputProperty(pair[0], pair[1]); } } + /** + * Sets the paramters for the transformer. + */ + private void setTransformationParameters() { + for (final Enumeration enumeration = params.keys(); enumeration.hasMoreElements(); ) { + final String name = (String) enumeration.nextElement(); + final String value = (String) params.get(name); + transformer.setParameter(name, value); + } + } + /** * return the Transformer factory associated to this liaison. * @return the Transformer factory associated to this liaison. @@ -426,8 +439,7 @@ public class TraXLiaison implements XSLTLiaison3, ErrorListener, XSLTLoggerAware * @param value the value of the parameter */ public void addParam(String name, String value) { - final String[] pair = new String[]{name, value}; - params.addElement(pair); + params.put(name, value); } /** @@ -552,4 +564,4 @@ public class TraXLiaison implements XSLTLiaison3, ErrorListener, XSLTLoggerAware setOutputProperty(prop.getName(), prop.getValue()); } } -} +} \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index f7813efe6..c7165675a 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -27,6 +27,10 @@ import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; import java.util.Random; import java.util.Stack; import java.util.StringTokenizer; @@ -85,7 +89,7 @@ public class FileUtils { * * @return a new instance of FileUtils. * @deprecated since 1.7. - * Use getFileUtils instead, + * Use getFileUtils instead, * FileUtils do not have state. */ public static FileUtils newFileUtils() { @@ -617,7 +621,7 @@ public class FileUtils { * * @return the native version of the specified path or * an empty string if the path is null or empty. - * + * * @since ant 1.7 * @see PathTokenizer */ @@ -1342,5 +1346,139 @@ public class FileUtils { file.delete(); } } -} + /** + * Calculates the relative path between to files. + *

    + * Implementation note:
    This function my throw an IOException if an + * I/O error occurs because its use of the canonical pathname may require + * filesystem queries. + *

    + * + * @param fromFile + * the File to calculate the path from + * @param toFile + * the File to calculate the path to + * @return + * @throws Exception + * @see {@link File#getCanonicalPath()} + * + * @since Ant 1.7 + */ + public static String getRelativePath( + File fromFile, + File toFile + ) throws Exception { + String fromPath = fromFile.getCanonicalPath(); + String toPath = toFile.getCanonicalPath(); + + // build the path stack info to compare + String[] fromPathStack = getPathStack(fromPath); + String[] toPathStack = getPathStack(toPath); + + if (0 < toPathStack.length && 0 < fromPathStack.length) { + if (!fromPathStack[0].equals(toPathStack[0])) { + // not the same device (would be "" on Linux/Unix) + + return getPath(Arrays.asList(toPathStack)); + } + } else { + // no comparison possible + return getPath(Arrays.asList(toPathStack)); + } + + int minLength = Math + .min(fromPathStack.length, toPathStack.length); + + int same = 1; + + // get index of parts which are equal + for (; same < minLength; same++) { + if (!fromPathStack[same].equals(toPathStack[same])) { + break; + } + } + + List relativePathStack = new ArrayList(); + + // if "from" part is longer, fill it up with ".." + // to reach path which is equal to both paths + for (int i = same; i < fromPathStack.length; i++) { + relativePathStack.add(".."); + } + + // fill it up path with parts which were not equal + for (int i = same; i < toPathStack.length; i++) { + relativePathStack.add(toPathStack[i]); + } + + return getPath(relativePathStack); + } + + /** + * Gets all names of the path as an array of Strings. + * + * @param path + * to get names from + * @return Strings, never null + * + * @since Ant 1.7 + */ + public static String[] getPathStack(String path) { + String normalizedPath = path.replace(File.separatorChar, '/'); + + // since Java 1.4 + //return normalizedPath.split("/"); + // workaround for Java 1.2-1.3 + Object[] tokens = StringUtils.split(normalizedPath, '/').toArray(); + String[] rv = new String[tokens.length]; + System.arraycopy(tokens, 0, rv, 0, tokens.length); + + return rv; + } + + /** + * Gets path from a List of Strings. + * + * @param pathStack + * List of Strings to be concated + * as a path. + * @return String, never null + * + * @since Ant 1.7 + */ + public static String getPath(List pathStack) { + // can safely use '/' because Windows understands '/' as separator + return getPath(pathStack, '/'); + } + + /** + * Gets path from a List of Strings. + * + * @param pathStack + * List of Strings to be concated + * as a path. + * @param separatorChar + * char to be used as separator between names in + * path + * @return String, never null + * + * @since Ant 1.7 + */ + public static String getPath(final List pathStack, final char separatorChar) { + final StringBuffer buffer = new StringBuffer(); + + final Iterator iter = pathStack.iterator(); + if (iter.hasNext()) { + buffer.append(iter.next()); + } + + while (iter.hasNext()) { + buffer.append(separatorChar); + buffer.append(iter.next()); + } + + return buffer.toString(); + } + +} \ No newline at end of file diff --git a/src/testcases/org/apache/tools/ant/taskdefs/StyleTest.java b/src/testcases/org/apache/tools/ant/taskdefs/StyleTest.java index 18f05e59e..be6063565 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/StyleTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/StyleTest.java @@ -86,7 +86,6 @@ public class StyleTest extends BuildFileTest { "new-value"); } - public void testDefaultMapper() throws Exception { testDefaultMapper("testDefaultMapper"); } @@ -149,6 +148,32 @@ public class StyleTest extends BuildFileTest { expectFileContains("testWithUrlResource", "out/out.xml", "set='value'"); } + public void testFilenameAsParam() throws Exception { + executeTarget("testFilenameAsParam"); + assertFileContains("out/out/one.txt", "filename='one.xml'"); + assertFileContains("out/out/two.txt", "filename='two.xml'"); + assertFileContains("out/out/three.txt", "filename='three.xml'"); + assertFileContains("out/out/dir/four.txt", "filename='four.xml'"); + assertFileContains("out/out/dir/four.txt", "filedir ='-not-set-'"); + } + + public void testFilenameAsParamNoSetting() throws Exception { + executeTarget("testFilenameAsParamNoSetting"); + assertFileContains("out/out/one.txt", "filename='-not-set-'"); + assertFileContains("out/out/two.txt", "filename='-not-set-'"); + assertFileContains("out/out/three.txt", "filename='-not-set-'"); + assertFileContains("out/out/dir/four.txt", "filename='-not-set-'"); + } + + public void testFilenameAndFiledirAsParam() throws Exception { + executeTarget("testFilenameAndFiledirAsParam"); + assertFileContains("out/out/one.txt", "filename='one.xml'"); + assertFileContains("out/out/one.txt", "filedir =''"); + assertFileContains("out/out/dir/four.txt", "filename='four.xml'"); + assertFileContains("out/out/dir/four.txt", "filedir ='dir'"); + } + + // ************* copied from ConcatTest ************* // ------------------------------------------------------ @@ -166,25 +191,23 @@ public class StyleTest extends BuildFileTest { finally { FileUtils.close(r); } - } - private String getFileString(String target, String filename) + private void expectFileContains( + String target, String filename, String contains) throws IOException { executeTarget(target); - return getFileString(filename); + assertFileContains(filename, contains); } - private void expectFileContains( - String target, String filename, String contains) - throws IOException - { - String content = getFileString(target, filename); + private void assertFileContains(String filename, String contains) throws IOException { + String content = getFileString(filename); assertTrue( - "expecting file " + filename + " to contain " + - contains + - " but got " + content, content.indexOf(contains) > -1); + "expecting file " + filename + + " to contain " + contains + + " but got " + content, + content.indexOf(contains) > -1); } -} +} \ No newline at end of file