git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@685887 13f79535-47bb-0310-9956-ffa450edef68master
@@ -257,6 +257,16 @@ Other changes: | |||||
write. | write. | ||||
Bugzilla Report 45081. | Bugzilla Report 45081. | ||||
* The filename file selector has a new attribute regex that allows | |||||
files to be selected by matching their names against a regular | |||||
expression. | |||||
Bugzilla Report 45284 | |||||
* The name resource selector has a new attribute regex that allows | |||||
resources to be selected by matching their names against a regular | |||||
expression. | |||||
Bugzilla Report 45284 | |||||
Changes from Ant 1.7.0 TO Ant 1.7.1 | Changes from Ant 1.7.0 TO Ant 1.7.1 | ||||
============================================= | ============================================= | ||||
@@ -503,8 +503,14 @@ platforms. | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">name</td> | <td valign="top">name</td> | ||||
<td valign="top">The name pattern to test</td> | |||||
<td align="center" valign="top">Yes</td> | |||||
<td valign="top">The name pattern to test using standard Ant | |||||
patterns.</td> | |||||
<td valign="top" align="center" rowspan="2">Exactly one of | |||||
the two</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">regex</td> | |||||
<td valign="top">The regular expression matching files to select.</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">casesensitive</td> | <td valign="top">casesensitive</td> | ||||
@@ -435,7 +435,12 @@ | |||||
<td valign="top">The name of files to select. The name parameter | <td valign="top">The name of files to select. The name parameter | ||||
can contain the standard Ant wildcard characters. | can contain the standard Ant wildcard characters. | ||||
</td> | </td> | ||||
<td valign="top" align="center">Yes</td> | |||||
<td valign="top" align="center" rowspan="2">Exactly one of | |||||
the two</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">regex</td> | |||||
<td valign="top">The regular expression matching files to select.</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">casesensitive</td> | <td valign="top">casesensitive</td> | ||||
@@ -17,17 +17,31 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.types.resources.selectors; | package org.apache.tools.ant.types.resources.selectors; | ||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.types.RegularExpression; | |||||
import org.apache.tools.ant.types.Resource; | import org.apache.tools.ant.types.Resource; | ||||
import org.apache.tools.ant.types.selectors.SelectorUtils; | import org.apache.tools.ant.types.selectors.SelectorUtils; | ||||
import org.apache.tools.ant.util.regexp.Regexp; | |||||
/** | /** | ||||
* Name ResourceSelector. | * Name ResourceSelector. | ||||
* @since Ant 1.7 | * @since Ant 1.7 | ||||
*/ | */ | ||||
public class Name implements ResourceSelector { | public class Name implements ResourceSelector { | ||||
private String regex = null; | |||||
private String pattern; | private String pattern; | ||||
private boolean cs = true; | private boolean cs = true; | ||||
// caches for performance reasons | |||||
private RegularExpression reg; | |||||
private Regexp expression; | |||||
private Project project; | |||||
public void setProject(Project p) { | |||||
project = p; | |||||
} | |||||
/** | /** | ||||
* Set the pattern to compare names against. | * Set the pattern to compare names against. | ||||
* @param n the pattern String to set. | * @param n the pattern String to set. | ||||
@@ -44,6 +58,23 @@ public class Name implements ResourceSelector { | |||||
return pattern; | return pattern; | ||||
} | } | ||||
/** | |||||
* Set the regular expression to compare names against. | |||||
* @param r the regex to set. | |||||
*/ | |||||
public void setRegex(String r) { | |||||
regex = r; | |||||
reg = null; | |||||
} | |||||
/** | |||||
* Get the regular expression used by this Name ResourceSelector. | |||||
* @return the String selection pattern. | |||||
*/ | |||||
public String getRegex() { | |||||
return regex; | |||||
} | |||||
/** | /** | ||||
* Set whether the name comparisons are case-sensitive. | * Set whether the name comparisons are case-sensitive. | ||||
* @param b boolean case-sensitivity flag. | * @param b boolean case-sensitivity flag. | ||||
@@ -67,11 +98,27 @@ public class Name implements ResourceSelector { | |||||
*/ | */ | ||||
public boolean isSelected(Resource r) { | public boolean isSelected(Resource r) { | ||||
String n = r.getName(); | String n = r.getName(); | ||||
if (SelectorUtils.match(pattern, n, cs)) { | |||||
if (matches(n)) { | |||||
return true; | return true; | ||||
} | } | ||||
String s = r.toString(); | String s = r.toString(); | ||||
return s.equals(n) ? false : SelectorUtils.match(pattern, s, cs); | |||||
return s.equals(n) ? false : matches(s); | |||||
} | } | ||||
private boolean matches(String name) { | |||||
if (pattern != null) { | |||||
return SelectorUtils.match(pattern, name, cs); | |||||
} else { | |||||
if (reg == null) { | |||||
reg = new RegularExpression(); | |||||
reg.setPattern(regex); | |||||
expression = reg.getRegexp(project); | |||||
} | |||||
int options = Regexp.MATCH_DEFAULT; | |||||
if (!cs) { | |||||
options |= Regexp.MATCH_CASE_INSENSITIVE; | |||||
} | |||||
return expression.matches(name, options); | |||||
} | |||||
} | |||||
} | } |
@@ -22,6 +22,8 @@ import java.io.File; | |||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.types.Parameter; | import org.apache.tools.ant.types.Parameter; | ||||
import org.apache.tools.ant.types.RegularExpression; | |||||
import org.apache.tools.ant.util.regexp.Regexp; | |||||
/** | /** | ||||
* Selector that filters files based on the filename. | * Selector that filters files based on the filename. | ||||
@@ -31,6 +33,7 @@ import org.apache.tools.ant.types.Parameter; | |||||
public class FilenameSelector extends BaseExtendSelector { | public class FilenameSelector extends BaseExtendSelector { | ||||
private String pattern = null; | private String pattern = null; | ||||
private String regex = null; | |||||
private boolean casesensitive = true; | private boolean casesensitive = true; | ||||
private boolean negated = false; | private boolean negated = false; | ||||
@@ -40,6 +43,12 @@ public class FilenameSelector extends BaseExtendSelector { | |||||
public static final String CASE_KEY = "casesensitive"; | public static final String CASE_KEY = "casesensitive"; | ||||
/** Used for parameterized custom selector */ | /** Used for parameterized custom selector */ | ||||
public static final String NEGATE_KEY = "negate"; | public static final String NEGATE_KEY = "negate"; | ||||
/** Used for parameterized custom selector */ | |||||
public static final String REGEX_KEY = "regex"; | |||||
// caches for performance reasons | |||||
private RegularExpression reg; | |||||
private Regexp expression; | |||||
/** | /** | ||||
* Creates a new <code>FilenameSelector</code> instance. | * Creates a new <code>FilenameSelector</code> instance. | ||||
@@ -53,19 +62,14 @@ public class FilenameSelector extends BaseExtendSelector { | |||||
*/ | */ | ||||
public String toString() { | public String toString() { | ||||
StringBuffer buf = new StringBuffer("{filenameselector name: "); | StringBuffer buf = new StringBuffer("{filenameselector name: "); | ||||
if (pattern != null) { | |||||
buf.append(pattern); | buf.append(pattern); | ||||
buf.append(" negate: "); | |||||
if (negated) { | |||||
buf.append("true"); | |||||
} else { | |||||
buf.append("false"); | |||||
} | } | ||||
buf.append(" casesensitive: "); | |||||
if (casesensitive) { | |||||
buf.append("true"); | |||||
} else { | |||||
buf.append("false"); | |||||
if (regex != null) { | |||||
buf.append(regex).append(" [as regular expression]"); | |||||
} | } | ||||
buf.append(" negate: ").append(negated); | |||||
buf.append(" casesensitive: ").append(casesensitive); | |||||
buf.append("}"); | buf.append("}"); | ||||
return buf.toString(); | return buf.toString(); | ||||
} | } | ||||
@@ -86,6 +90,17 @@ public class FilenameSelector extends BaseExtendSelector { | |||||
this.pattern = pattern; | this.pattern = pattern; | ||||
} | } | ||||
/** | |||||
* The regular expression the file name will be matched against. | |||||
* | |||||
* @param pattern the regular expression that any filename must match | |||||
* against in order to be selected. | |||||
*/ | |||||
public void setRegex(String pattern) { | |||||
this.regex = pattern; | |||||
this.reg = null; | |||||
} | |||||
/** | /** | ||||
* Whether to ignore case when checking filenames. | * Whether to ignore case when checking filenames. | ||||
* | * | ||||
@@ -125,6 +140,8 @@ public class FilenameSelector extends BaseExtendSelector { | |||||
parameters[i].getValue())); | parameters[i].getValue())); | ||||
} else if (NEGATE_KEY.equalsIgnoreCase(paramname)) { | } else if (NEGATE_KEY.equalsIgnoreCase(paramname)) { | ||||
setNegate(Project.toBoolean(parameters[i].getValue())); | setNegate(Project.toBoolean(parameters[i].getValue())); | ||||
} else if (REGEX_KEY.equalsIgnoreCase(paramname)) { | |||||
setRegex(parameters[i].getValue()); | |||||
} else { | } else { | ||||
setError("Invalid parameter " + paramname); | setError("Invalid parameter " + paramname); | ||||
} | } | ||||
@@ -138,8 +155,10 @@ public class FilenameSelector extends BaseExtendSelector { | |||||
* | * | ||||
*/ | */ | ||||
public void verifySettings() { | public void verifySettings() { | ||||
if (pattern == null) { | |||||
setError("The name attribute is required"); | |||||
if (pattern == null && regex == null) { | |||||
setError("The name or regex attribute is required"); | |||||
} else if (pattern != null && regex != null) { | |||||
setError("Only one of name and regex attribute is allowed"); | |||||
} | } | ||||
} | } | ||||
@@ -157,9 +176,21 @@ public class FilenameSelector extends BaseExtendSelector { | |||||
*/ | */ | ||||
public boolean isSelected(File basedir, String filename, File file) { | public boolean isSelected(File basedir, String filename, File file) { | ||||
validate(); | validate(); | ||||
if (pattern != null) { | |||||
return (SelectorUtils.matchPath(pattern, filename, | return (SelectorUtils.matchPath(pattern, filename, | ||||
casesensitive) == !(negated)); | casesensitive) == !(negated)); | ||||
} else { | |||||
if (reg == null) { | |||||
reg = new RegularExpression(); | |||||
reg.setPattern(regex); | |||||
expression = reg.getRegexp(getProject()); | |||||
} | |||||
int options = Regexp.MATCH_DEFAULT; | |||||
if (!casesensitive) { | |||||
options |= Regexp.MATCH_CASE_INSENSITIVE; | |||||
} | |||||
return expression.matches(filename, options) == !negated; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -0,0 +1,64 @@ | |||||
<?xml version="1.0"?> | |||||
<!-- | |||||
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. | |||||
--> | |||||
<project xmlns:au="antlib:org.apache.ant.antunit" default="antunit" | |||||
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
<import file="../../../antunit-base.xml" /> | |||||
<property name="dir" location="testdir"/> | |||||
<property name="file" value="testfile"/> | |||||
<target name="createTestdir"> | |||||
<mkdir dir="${dir}"/> | |||||
<touch file="${dir}/${file}"/> | |||||
</target> | |||||
<target name="tearDown"> | |||||
<delete dir="${dir}"/> | |||||
</target> | |||||
<target name="testPattern" depends="createTestdir"> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="1"> | |||||
<restrict> | |||||
<fileset dir="${dir}"/> | |||||
<rsel:name name="*"/> | |||||
</restrict> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="0"> | |||||
<restrict> | |||||
<fileset dir="${dir}"/> | |||||
<rsel:name name=".*"/> | |||||
</restrict> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
</target> | |||||
<target name="testRegex" depends="createTestdir"> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="1"> | |||||
<restrict> | |||||
<fileset dir="${dir}"/> | |||||
<rsel:name regex=".*"/> | |||||
</restrict> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
</target> | |||||
</project> |
@@ -0,0 +1,74 @@ | |||||
<?xml version="1.0"?> | |||||
<!-- | |||||
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. | |||||
--> | |||||
<project xmlns:au="antlib:org.apache.ant.antunit" default="antunit"> | |||||
<import file="../../antunit-base.xml" /> | |||||
<property name="dir" location="testdir"/> | |||||
<property name="file" value="testfile"/> | |||||
<target name="createTestdir"> | |||||
<mkdir dir="${dir}"/> | |||||
<touch file="${dir}/${file}"/> | |||||
</target> | |||||
<target name="tearDown"> | |||||
<delete dir="${dir}"/> | |||||
</target> | |||||
<target name="testPattern" depends="createTestdir"> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="1"> | |||||
<fileset dir="${dir}"> | |||||
<filename name="*"/> | |||||
</fileset> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="0"> | |||||
<fileset dir="${dir}"> | |||||
<filename name="*" negate="true"/> | |||||
</fileset> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="0"> | |||||
<fileset dir="${dir}"> | |||||
<filename name=".*"/> | |||||
</fileset> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
</target> | |||||
<target name="testRegex" depends="createTestdir"> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="1"> | |||||
<fileset dir="${dir}"> | |||||
<filename regex=".*"/> | |||||
</fileset> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
<au:assertTrue> | |||||
<resourcecount when="equal" count="0"> | |||||
<fileset dir="${dir}"> | |||||
<filename regex=".*" negate="true"/> | |||||
</fileset> | |||||
</resourcecount> | |||||
</au:assertTrue> | |||||
</target> | |||||
</project> |
@@ -51,7 +51,7 @@ public class FilenameSelectorTest extends BaseSelectorTest { | |||||
s.isSelected(basedir,filenames[0],files[0]); | s.isSelected(basedir,filenames[0],files[0]); | ||||
fail("FilenameSelector did not check for required fields"); | fail("FilenameSelector did not check for required fields"); | ||||
} catch (BuildException be1) { | } catch (BuildException be1) { | ||||
assertEquals("The name attribute is required", be1.getMessage()); | |||||
assertEquals("The name or regex attribute is required", be1.getMessage()); | |||||
} | } | ||||
s = (FilenameSelector)getInstance(); | s = (FilenameSelector)getInstance(); | ||||