Hi,

I have some Ant changes that I'd like to put forward for possible
inclusion in future versions of Ant. These changes are all aimed at
making it easier to process file paths and text in various ways.


1. "mapperfilter", a ChainableFilterReader that complements
"filtermapper". Whereas "filtermapper" allows file paths to be treated
as arbitrary text and manipulated by text filters, "mapperfilter" allows
arbitrary text to be treated as file paths and manipulated by mappers.
For example,
<filterchain>
    <mapperfilter>
        <globmapper from="*.java" to="*.class"/>
    </mapperfilter>
</filterchain>


2. "subpathmapper", a Mapper for conceptually splitting up file paths
into their constituent directory and file name elements and selecting a
sequence of those elements. For example, selecting only the directory
part of a filename.


The above two changes are primarily aimed at reducing the need to use
regular expressions to process filenames.


3. Nested FilterChains in the property task. Currently, in order to take
the value of one property and process it into a different property,
there are two ways:

i) Use "pathconvert" and mappers - only appropriate for file and path values
ii) Write the property to a file and read it in with FilterChains.


The use of the file in the second instance can be avoided by the use of
FilterChains when setting the value of a property. For example:

<!-- versionstring has the following multi-line value:

Product: Widget
Version: 0.01
-->
<property name="htmlversionstring" value="${versionstring}>

    <filterchain>
        <prefixlines prefix="&lt;br&gt;"/>
    </filterchain>
</property>


The changes needed for the above features are fairly small. I attach a
patch, including some tests and documentation changes.


Is this of any interest? Are these changes in line with Ant philosophy?


Thanks,


Daniel


Index: src/tests/junit/org/apache/tools/ant/filters/TokenFilterTest.java
===================================================================
--- src/tests/junit/org/apache/tools/ant/filters/TokenFilterTest.java   
(revision 465935)
+++ src/tests/junit/org/apache/tools/ant/filters/TokenFilterTest.java   
(working copy)
@@ -206,6 +206,22 @@
                            "Hello World");
     }
 
+    
+    public void testMapperFilterGlob() throws IOException {
+        expectFileContains("mapperfilter-glob", "result/mapperfilter-glob",
+                "a.class b.class");
+    }
+    
+    public void testMapperFilterComposite() throws IOException {
+        expectFileContains("mapperfilter-composite", 
"result/mapperfilter-composite",
+                "a.java a.class");
+    }
+    
+    public void testMapperFilterComposite2() throws IOException {
+        expectFileContains("mapperfilter-composite2", 
"result/mapperfilter-composite2",
+                "a.java a.class");
+    }
+    
     // ------------------------------------------------------
     //   Helper methods
     // -----------------------------------------------------
Index: src/tests/junit/org/apache/tools/ant/taskdefs/PropertyTest.java
===================================================================
--- src/tests/junit/org/apache/tools/ant/taskdefs/PropertyTest.java     
(revision 465935)
+++ src/tests/junit/org/apache/tools/ant/taskdefs/PropertyTest.java     
(working copy)
@@ -108,4 +108,16 @@
         expectLog("thisIsNotACircularReference", "b is A/A/A");
     }
 
+    public void testFilter1() {
+        expectLog("filter1", "testprop1=ac");
+    }
+
+    public void testFilter2() {
+        expectLog("filter2", "testprop1=a.class,b.class");
+    }
+
+    public void testFilter3() {
+        expectLog("filter3", "testprop1=aa, testprop3=xxyy, testprop4=ppzz");
+    }
+    
 }
Index: src/tests/junit/org/apache/tools/ant/util/SubPathMapperTest.java
===================================================================
--- src/tests/junit/org/apache/tools/ant/util/SubPathMapperTest.java    
(revision 0)
+++ src/tests/junit/org/apache/tools/ant/util/SubPathMapperTest.java    
(revision 0)
@@ -0,0 +1,53 @@
+/*
+ *  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.util;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for the &lt;subpathmapper&gt; mapper.
+ *
+ */
+public class SubPathMapperTest extends BuildFileTest {
+    public SubPathMapperTest(String name) {
+        super(name);
+    }
+    public void setUp() {
+        configureProject("src/etc/testcases/types/mappers/subpathmapper.xml");
+    }
+
+    public void test1() {
+        executeTarget("1");
+    }
+
+    public void test2() {
+        executeTarget("2");
+    }
+    
+    public void test3() {
+        executeTarget("3");
+    }
+
+    public void test4() {
+        executeTarget("4");
+    }
+
+}
+
+
Index: src/main/org/apache/tools/ant/filters/MapperFilter.java
===================================================================
--- src/main/org/apache/tools/ant/filters/MapperFilter.java     (revision 0)
+++ src/main/org/apache/tools/ant/filters/MapperFilter.java     (revision 0)
@@ -0,0 +1,52 @@
+/*
+ *  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.filters;
+
+import org.apache.tools.ant.util.CompositeMapper;
+import org.apache.tools.ant.util.FileNameMapper;
+import org.apache.tools.ant.util.StringUtils;
+
+/** Filter for applying mapper transformations to text. A MapperFilter is
+ * an implicit CompositeMapper, and can contain other mapper elements.
+ */
+public class MapperFilter extends TokenFilter.ChainableReaderFilter {
+    
+    private String delimOutput = "";
+    private CompositeMapper mapper = new CompositeMapper();
+    
+    public void setDelimOutput(String delimOutput) {
+        this.delimOutput = StringUtils.resolveBackSlash(delimOutput);
+    }
+    
+    public synchronized void add(FileNameMapper fileNameMapper) {
+        mapper.add(fileNameMapper);
+    }
+    
+    public String filter(String string) {
+        String[] names = mapper.mapFileName(string);
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; names != null && i < names.length; i++) {
+            if (i > 0) {
+                sb.append(delimOutput);
+            }
+            sb.append(names[i]);
+        }
+        return sb.toString();
+    }
+    
+}
Index: src/main/org/apache/tools/ant/taskdefs/Property.java
===================================================================
--- src/main/org/apache/tools/ant/taskdefs/Property.java        (revision 
465935)
+++ src/main/org/apache/tools/ant/taskdefs/Property.java        (working copy)
@@ -22,6 +22,8 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
 import java.net.URL;
 import java.util.Enumeration;
 import java.util.Properties;
@@ -32,6 +34,8 @@
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.PropertyHelper;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.filters.util.ChainReaderHelper;
+import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
 
@@ -79,6 +83,7 @@
     protected String env;
     protected Reference ref;
     protected String prefix;
+    protected Vector filterChains;
     private Project fallback;
 
     protected boolean userProperty; // set read-only properties
@@ -219,6 +224,30 @@
     }
 
     /**
+     * Add a FilterChain to be applied to values specified for properties.
+     * @return a filter chain object.
+     * @since Ant 1.8
+     */
+    public FilterChain createFilterChain() {
+        if (filterChains == null) {
+            filterChains = new Vector();
+        }
+        FilterChain filterChain = new FilterChain();
+        filterChains.addElement(filterChain);
+        return filterChain;
+    }
+
+    /**
+     * Get the filterchains being applied to this operation.
+     *
+     * @return a vector of FilterChain objects.
+     */
+    protected Vector getFilterChains() {
+        return filterChains;
+    }
+
+
+    /**
      * Sets a reference to an Ant datatype
      * declared elsewhere.
      * Only yields reasonable results for references
@@ -563,6 +592,23 @@
      * @param v value to set
      */
     protected void addProperty(String n, String v) {
+        if (filterChains != null) {
+            ChainReaderHelper crh = new ChainReaderHelper();
+            crh.setPrimaryReader(new StringReader(v));
+            crh.setFilterChains(filterChains);
+            Reader in = crh.getAssembledReader();
+            StringBuffer sb = new StringBuffer();
+            char[] buffer = new char[256];
+            try {
+                for (int charsRead = 0; (charsRead = in.read(buffer)) >= 0;) {
+                    sb.append(buffer, 0, charsRead);
+                }
+                in.close();
+            } catch (IOException e) {
+                throw new BuildException("Error applying filter", e);
+            }
+            v = sb.toString();
+        }
         if (userProperty) {
             if (getProject().getUserProperty(n) == null) {
                 getProject().setInheritedProperty(n, v);
Index: src/main/org/apache/tools/ant/types/defaults.properties
===================================================================
--- src/main/org/apache/tools/ant/types/defaults.properties     (revision 
465935)
+++ src/main/org/apache/tools/ant/types/defaults.properties     (working copy)
@@ -18,6 +18,7 @@
 mavenrepository=org.apache.tools.ant.taskdefs.repository.MavenRepository
 scriptselector=org.apache.tools.ant.types.optional.ScriptSelector
 scriptmapper=org.apache.tools.ant.types.optional.ScriptMapper
+mapperfilter=org.apache.tools.ant.filters.MapperFilter
 
 # different filename mappers
 identitymapper=org.apache.tools.ant.util.IdentityMapper
@@ -29,6 +30,7 @@
 unpackagemapper=org.apache.tools.ant.util.UnPackageNameMapper
 compositemapper=org.apache.tools.ant.util.CompositeMapper
 chainedmapper=org.apache.tools.ant.util.ChainedMapper
+subpathmapper=org.apache.tools.ant.util.SubPathMapper
 filtermapper=org.apache.tools.ant.types.mappers.FilterMapper
 
 #this condition is in here because it is the sole
Index: src/main/org/apache/tools/ant/types/Mapper.java
===================================================================
--- src/main/org/apache/tools/ant/types/Mapper.java     (revision 465935)
+++ src/main/org/apache/tools/ant/types/Mapper.java     (working copy)
@@ -282,6 +282,8 @@
                                 "org.apache.tools.ant.util.PackageNameMapper");
             implementations.put("unpackage",
                                 
"org.apache.tools.ant.util.UnPackageNameMapper");
+            implementations.put("subpath",
+                                "org.apache.tools.ant.util.SubPathMapper");
         }
 
         /**
@@ -289,7 +291,8 @@
          */
         public String[] getValues() {
             return new String[] {"identity", "flatten", "glob",
-                                 "merge", "regexp", "package", "unpackage"};
+                                 "merge", "regexp", "package", "unpackage",
+                                 "subpath"};
         }
 
         /**
Index: src/main/org/apache/tools/ant/util/SubPathMapper.java
===================================================================
--- src/main/org/apache/tools/ant/util/SubPathMapper.java       (revision 0)
+++ src/main/org/apache/tools/ant/util/SubPathMapper.java       (revision 0)
@@ -0,0 +1,83 @@
+/*
+ *  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.util;
+
+import java.io.File;
+import java.util.StringTokenizer;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+
+/**
+ * Mapper for extracting subpaths from a file location.
+ * 
+ * <p>Elements of the path that fall between the control points selected by
+ * <code>from</code> and <code>to</code> are selected by the mapper.
+ * 
+ * <p>Starting from the left, control points are numbered 0, 1, 2 and so on, 
where
+ * 0 precedes the first directory or file element.
+ * <p>Starting from the right, control points are numbered -1, -2, -3 and so 
on,
+ * where -1 follows the last directory or file element.
+ * 
+ */
+public class SubPathMapper implements FileNameMapper {
+
+    private int from = 0;
+    private int to = Integer.MAX_VALUE;
+    
+    public void setFrom(String from) {
+        this.from = Integer.parseInt(from);
+    }
+
+    public void setTo(String to) {
+        this.to = Integer.parseInt(to);
+    }
+    
+    public String[] mapFileName(String sourceFileName) {
+        StringTokenizer st = new StringTokenizer(sourceFileName, 
File.separator);
+        int tokenCount = st.countTokens();
+        int firstToken, lastToken;
+        if (from >= 0) {
+            firstToken = from;
+        } else {
+            firstToken = Math.max(0, tokenCount + from + 1);
+        }
+        if (to >= 0) {
+            lastToken = Math.min(to, tokenCount);
+        } else {
+            lastToken = Math.min(tokenCount, tokenCount + to + 1);
+        }
+        if (lastToken > firstToken && firstToken < tokenCount) {
+            for (int i = 0; i < firstToken; i++) {
+                st.nextToken();
+            }
+            StringBuffer sb = new StringBuffer();
+            for (int i = firstToken; i < lastToken; i++) {
+                if (i > firstToken) {
+                    sb.append(File.separatorChar);
+                }
+                sb.append(st.nextToken());
+            }
+            return new String[] { sb.toString() };
+        } else {
+            return new String[0];
+        }
+
+    }
+
+}
Index: src/etc/testcases/taskdefs/property.xml
===================================================================
--- src/etc/testcases/taskdefs/property.xml     (revision 465935)
+++ src/etc/testcases/taskdefs/property.xml     (working copy)
@@ -45,5 +45,37 @@
     <property file="property5.properties"/>
     <echo>b is ${b}</echo>
   </target>
+  
+  <target name="filter1">
+    <property name="testprop1" value="abc">
+      <filterchain>
+        <deletecharacters chars="b"/>
+      </filterchain>
+    </property>
+    <echo message="testprop1=${testprop1}"/>
+  </target>
 
+  <target name="filter2">
+    <property name="testprop1" value="a.java${line.separator}b.java">
+      <filterchain>
+        <tokenfilter delimOutput=",">
+          <mapperfilter>
+            <globmapper from="*.java" to="*.class"/>
+          </mapperfilter>
+        </tokenfilter>
+      </filterchain>
+    </property>
+    <echo message="testprop1=${testprop1}"/>
+  </target>
+  
+  <target name="filter3">
+    <property name="testprop1" value="aa"/>
+    <property file="property1.properties">
+      <filterchain>
+        <replaceregex pattern="a" replace="p" flags="g"/>
+      </filterchain>
+    </property>
+    <echo message="testprop1=${testprop1}, testprop3=${testprop3}, 
testprop4=${testprop4}"/>      
+  </target>
+
 </project>
Index: src/etc/testcases/types/mappers/subpathmapper.xml
===================================================================
--- src/etc/testcases/types/mappers/subpathmapper.xml   (revision 0)
+++ src/etc/testcases/types/mappers/subpathmapper.xml   (revision 0)
@@ -0,0 +1,59 @@
+<project>
+  <import file="define.mapperresult.xml"/>
+
+  <target name="1">
+    <mapperresult input="a/b/c.java" output="a/b/c.java">
+      <subpathmapper from="0" to="-1"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="b/c.java">
+      <!--subpathmapper from="1" to="-1"/-->
+      <mapper type="subpath" from="1" to="-1"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="c.java">
+      <subpathmapper from="2" to="-1"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="">
+      <subpathmapper from="3" to="-1"/>
+    </mapperresult>
+  </target>
+  
+  <target name="2">
+    <mapperresult input="a/b/c.java" output="a/b/c.java">
+      <subpathmapper from="0" to="3"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="b/c.java">
+      <subpathmapper from="1" to="4"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="c.java">
+      <subpathmapper from="2" to="3"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="">
+      <subpathmapper from="3" to="3"/>
+    </mapperresult>
+  </target>
+
+  <target name="3">
+    <mapperresult input="a/b/c.java" output="a/b/c.java">
+      <subpathmapper from="-5" to="-1"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="a/b/c.java">
+      <subpathmapper from="-4" to="-1"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="b/c.java">
+      <subpathmapper from="-3" to="-1"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="c.java">
+      <subpathmapper from="-2" to="-1"/>
+    </mapperresult>
+    <mapperresult input="a/b/c.java" output="">
+      <subpathmapper from="-1" to="-1"/>
+    </mapperresult>
+  </target>
+  
+  <target name="4">
+    <mapperresult input="a\b/c.java" output="a\b/c.java">
+      <subpathmapper from="0" to="-1"/>
+    </mapperresult>
+  </target>
+
+</project>
Index: src/etc/testcases/filters/tokenfilter.xml
===================================================================
--- src/etc/testcases/filters/tokenfilter.xml   (revision 465935)
+++ src/etc/testcases/filters/tokenfilter.xml   (working copy)
@@ -340,4 +340,49 @@
                   replace="bye\1world"/>
   </target>
 
+  <target name="mapperfilter-glob">
+    <concat destfile="result/mapperfilter-glob">
+      a.java
+      b.java
+      <filterchain>
+        <tokenfilter delimoutput=" ">
+          <trim/>
+          <mapperfilter>
+            <globmapper from="*.java" to="*.class"/>
+          </mapperfilter>
+        </tokenfilter>
+      </filterchain>
+    </concat>
+  </target>
+    
+  <target name="mapperfilter-composite">
+    <concat destfile="result/mapperfilter-composite">
+      a.java
+      <filterchain>
+        <tokenfilter delimoutput=" ">
+          <trim/>
+          <mapperfilter delimOutput=" ">
+            <identitymapper/>
+            <globmapper from="*.java" to="*.class"/>
+          </mapperfilter>
+        </tokenfilter>
+      </filterchain>
+    </concat>
+  </target>
+    
+  <target name="mapperfilter-composite2">
+    <concat destfile="result/mapperfilter-composite2">
+      a.java
+      <filterchain>
+        <tokenfilter>
+          <trim/>
+        </tokenfilter>
+        <mapperfilter delimOutput=" ">
+          <identitymapper/>
+          <globmapper from="*.java" to="*.class"/>
+        </mapperfilter>
+        </filterchain>
+      </concat>
+  </target>
+    
 </project>
Index: docs/manual/CoreTasks/property.html
===================================================================
--- docs/manual/CoreTasks/property.html (revision 465935)
+++ docs/manual/CoreTasks/property.html (working copy)
@@ -57,6 +57,8 @@
 This also holds for properties loaded from a property file.</p>
 <p>A list of predefined properties can be found <a
 href="../using.html#built-in-props">here</a>.</p>
+<p>Nested <a href="../CoreTypes/filterchain.html">FilterChain</a>s can be
+applied to property values before they are set.</p>
 
 <h4>OpenVMS Users</h4>
 <p>With the <code>environment</code> attribute this task will load all defined
@@ -153,6 +155,10 @@
 <p><code>Property</code>'s <i>classpath</i> attribute is a <a
 href="../using.html#path">PATH like structure</a> and can also be set via a 
nested
 <i>classpath</i> element.</p>
+<h4>filterchain</h4>
+<p><a href="../CoreTypes/filterchain.html">FilterChain</a>s can be nested in 
the
+    property task. Values are passed through any FilterChains specified
+before being assigned to properties.</p>
 <h3>Examples</h3>
 <pre>  &lt;property name=&quot;foo.dist&quot; value=&quot;dist&quot;/&gt;</pre>
 <p>sets the property <code>foo.dist</code> to the value &quot;dist&quot;.</p>
Index: docs/manual/CoreTypes/mapper.html
===================================================================
--- docs/manual/CoreTypes/mapper.html   (revision 465935)
+++ docs/manual/CoreTypes/mapper.html   (working copy)
@@ -582,6 +582,34 @@
     <td valign="top"><code>${test.src.dir}/org/acme/AcmeTest.java</code></td>
   </tr>
 </table>
+<h4><a name="subpath-mapper">subpath (since Ant 1.8)</a></h4>
+  <p>This mapper decomposes a path into its separate directory and file names
+    and selects only a specified region of the path. For example, it can be 
used
+    to select only the directory part of a path.</p>
+  <p>The <code>from</code> and <code>to</code> values provided to the mapper
+    provide the starting and ending bounds for the selected path region. These
+    values can be either positive or negative:</p>
+<ul>
+  <li><b>Positive</b> values are counted from the beginning of
+    the path, where 0 is before the first directory or file name.</li>
+  <li><b>Negative</b> values are counted from the end of
+    the path, where -1 is after the last directory or file name.</li>
+</ul>
+<b>Example:</b>
+<blockquote><pre>
+&lt;mapper type="subpath" from="1" to="-1"&gt;
+&lt;subpathmapper from="1" to="-1"&gt;
+</pre></blockquote>
+<table border="1" cellpadding="2" cellspacing="0">
+  <tr>
+    <td valign="top"><b>Source file name</b></td>
+    <td valign="top"><b>Target file name</b></td>
+  </tr>
+  <tr>
+    <td valign="top"><code>a/b/X.java</code></td>
+    <td valign="top"><code>b/X.java</code></td>
+  </tr>
+</table>
 <h4><a name="composite-mapper">composite (since Ant 1.6.2)</a></h4>
   <p>This mapper implementation can contain multiple nested mappers.
     File mapping is performed by passing the source filename to each nested
Index: docs/manual/CoreTypes/filterchain.html
===================================================================
--- docs/manual/CoreTypes/filterchain.html      (revision 465935)
+++ docs/manual/CoreTypes/filterchain.html      (working copy)
@@ -122,6 +122,7 @@
 <a href="#tailfilter">TailFilter</a><br>
 <a href="#deletecharacters">DeleteCharacters</a><br>
 <a href="#concatfilter">ConcatFilter</a><br>
+<a href="#mapperfilter">MapperFilter</a><br>
 <a href="#tokenfilter">TokenFilter</a><br>
 
 <h3><a name="filterreader">FilterReader</a></h3>
@@ -962,7 +963,41 @@
 </pre></blockquote>
 
 
+<h3><a name="mapperfilter">MapperFilter</a></h3>
+<p>This filter behaves like a <a href="mapper.html#composite-mapper">composite
+    mapper</a>. Each line of the stream is treated like a file path. The filter
+contains <a href="mapper.html">mappers</a> that are applied to each line.</p>
+<p>Since a mapper can have multiple outputs, the parameter 
<code>delimOutput</code>
+can be set to separate between the output values.</p>
+  <p><em>since Ant 1.8</em></p>
+<table cellSpacing=0 cellPadding=2 border=1>
+  <tr>
+    <td vAlign=top><b>Parameter Name</b></td>
+    <td vAlign=top><b>Parameter Value</b></td>
+    <td vAlign=top align="center"><b>Required</b></td>
+  </tr>
+  <tr>
+    <td vAlign=top>delimOutput</td>
+    <td vAlign=top>
+      The string used to separate between elements of the output. This string
+      is only used when there are multiple values output from the mapper. The
+      default value is an empty string.
+    </td>
+    <td vAlign=top align="center">No</td>
+  </tr>
+</table>
+<h4>Examples:</h4>
 
+Treating each line of the input as a file path in the form "*.java", convert
+paths to the form "*.class":
+<blockquote><pre>
+&lt;filterchain&gt;
+    &lt;mapperfilter&gt;
+        &lt;globmapper from="*.java" to="*.class"/&gt;
+    &lt;/mapperfilter&gt;
+&lt;/filterchain&gt;
+</pre></blockquote>
+
 <h3><a name="tokenfilter">TokenFilter</a></h3>
 This filter tokenizes the inputstream into strings and passes these
 strings to filters of strings. Unlike the other filterreaders, this does
Index: build.xml
===================================================================
--- build.xml   (revision 465935)
+++ build.xml   (working copy)
@@ -1620,6 +1620,10 @@
     <condition property="junit.testcase" value="${testcase}">
       <available classname="${testcase}" classpathref="tests-classpath" />
     </condition>
+    
+    <condition property="junit.testcase" value="${junit.testedclass}Test">
+      <available classname="${junit.testedclass}Test" 
classpathref="tests-classpath" />        
+    </condition>
 
     <fail>Cannot locate test ${testcase}
       <condition>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to