diff --git a/WHATSNEW b/WHATSNEW
index 17a9215c1..31a74b0c1 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -17,6 +17,8 @@ Fixed bugs:
Other changes:
--------------
+* New task replaceregexp
+
* The attributes zipfile, jarfile, warfile and earfile (from the Zip,
Jar, War and Ear tasks) have been deprecated and superseded by a
new attribute "file".
diff --git a/build.xml b/build.xml
index 92a6e484f..ede62d8d5 100644
--- a/build.xml
+++ b/build.xml
@@ -174,6 +174,14 @@
classpathref="classpath"/>
+
+
+ * Task to do regular expression string replacements in a text + * file. The input file(s) must be able to be properly processed by + * a Reader instance. That is, they must be text only, no binary. + * + * The syntax of the regular expression depends on the implemtation that + * you choose to use. The system property+ * + * @author Matthew Inger + */ +public class ReplaceRegExp extends Task +{ + // Don't extend SedonaTaskContainer until we can delay building of + // the subtasks so variable of the current token works. + + private File file; + private String flags; + private boolean byline; + private Vector filesets; // Keep jdk 1.1 compliant so others can use this + private RegularExpression regex; + private Substitution subs; + + /*** + * Default Constructor + */ + public ReplaceRegExp() + { + super(); + this.file = null; + this.filesets = new Vector(); + this.flags = ""; + this.byline = false; + + this.regex = null; + this.subs = null; + } + + public void setFile(File file) + { + this.file = file; + } + + public void setMatch(String match) + { + if (regex != null) + throw new BuildException("Only one regular expression is allowed"); + + regex = new RegularExpression(); + regex.setPattern(match); + } + + public void setReplace(String replace) + { + if (subs != null) + throw new BuildException("Only one substitution expression is allowed"); + + subs = new Substitution(); + subs.setExpression(replace); + } + + public void setFlags(String flags) + { + this.flags = flags; + } + + public void setByLine(String byline) + { + Boolean res = Boolean.valueOf(byline); + if (res == null) + res = Boolean.FALSE; + this.byline = res.booleanValue(); + } + + public void addFileset(FileSet set) + { + filesets.add(set); + } + + public RegularExpression createRegularExpression() + { + if (regex != null) + throw new BuildException("Only one regular expression is allowed."); + + regex = new RegularExpression(); + return regex; + } + + public Substitution createSubstitution() + { + if (subs != null) + throw new BuildException("Only one substitution expression is allowed"); + + subs = new Substitution(); + return subs; + } + + + protected String doReplace(RegularExpression r, + Substitution s, + String input, + int options) + { + String res = input; + Regexp regexp = r.getRegexp(project); + + if (regexp.matches(input, options)) + { + res = regexp.substitute(input, s.getExpression(project), options); + } + + return res; + } + + /*** + * Perform the replace on the entire file + */ + protected void doReplace(File f, int options) + throws IOException + { + File parentDir = new File(f.getAbsolutePath()).getParentFile(); + File temp = File.createTempFile("replace", ".txt", parentDir); + + FileReader r = null; + FileWriter w = null; + + try + { + r = new FileReader(f); + w = new FileWriter(temp); + + BufferedReader br = new BufferedReader(r); + BufferedWriter bw = new BufferedWriter(w); + PrintWriter pw = new PrintWriter(bw); + + boolean changes = false; + + log("Replacing pattern '" + regex.getPattern(project) + "' with '" + subs.getExpression(project) + + "' in '" + f.getPath() + "'" + + (byline ? " by line" : "") + + (flags.length() > 0 ? " with flags: '" + flags + "'" : "") + + ".", + Project.MSG_WARN); + + if (byline) + { + LineNumberReader lnr = new LineNumberReader(br); + String line = null; + + while ((line = lnr.readLine()) != null) + { + String res = doReplace(regex, subs, line, options); + if (! res.equals(line)) + changes = true; + + pw.println(res); + } + pw.flush(); + } + else + { + int flen = (int)(f.length()); + char tmpBuf[] = new char[flen]; + int numread = 0; + int totread = 0; + while (numread != -1 && totread < flen) + { + numread = br.read(tmpBuf, totread, flen); + totread += numread; + } + + String buf = new String(tmpBuf); + + String res = doReplace(regex, subs, buf, options); + if (! res.equals(buf)) + changes = true; + + pw.println(res); + pw.flush(); + } + + r.close(); + r = null; + w.close(); + w = null; + + if (changes) + { + f.delete(); + temp.renameTo(f); + } + else + { + temp.delete(); + } + } + finally + { + try { if (r != null) r.close(); } + catch (Exception e) { }; + + try { if (w != null) r.close(); } + catch (Exception e) { }; + } + } + + public void execute() + throws BuildException + { + if (regex == null) + throw new BuildException("No expression to match."); + if (subs == null) + throw new BuildException("Nothing to replace expression with."); + + if (file != null && filesets.size() > 0) + throw new BuildException("You cannot supply the 'file' attribute and filesets at the same time."); + + + int options = 0; + + if (flags.indexOf('g') != -1) + options |= Regexp.REPLACE_ALL; + + if (flags.indexOf('i') != -1) + options |= Regexp.MATCH_CASE_INSENSITIVE; + + if (flags.indexOf('m') != -1) + options |= Regexp.MATCH_MULTILINE; + + if (flags.indexOf('s') != -1) + options |= Regexp.MATCH_SINGLELINE; + + if (file != null && file.exists()) + { + try + { + doReplace(file, options); + } + catch (IOException e) + { + log("An error occurred processing file: '" + file.getAbsolutePath() + "': " + e.toString(), + Project.MSG_ERR); + } + } + else if (file != null) + { + log("The following file is missing: '" + file.getAbsolutePath() + "'", + Project.MSG_ERR); + } + + int sz = filesets.size(); + for (int i=0;iant.regexp.regexpimpl
+ * will be the classname of the implementation that will be used (the default + * isorg.apache.tools.ant.util.regexp.JakartaOroRegexp
and + * requires the Jakarta Oro Package). + * + *+ * For jdk <= 1.3, there are two available implementations: + * org.apache.tools.ant.util.regexp.JakartaOroRegexp (the default) + * Requires the jakarta-oro package + * + * org.apache.tools.ant.util.regexp.JakartaRegexpRegexp + * Requires the jakarta-regexp package + * + * For jdk <= 1.4, and additional implementation is available: + * org.apache.tools.ant.util.regexp.Jdk14RegexpRegexp + * Requires the jdk 1.4 built in regular expression package. + *+ * + * Usage: + * + * Task declaration in the project: + * + * <taskdef name="replaceregexp" class="com.sedona.ant.taskdef.ReplaceRegExp" /> + * + * Call Syntax: + * + * <replaceregexp file="file" + * match="pattern" + * replace="pattern" + * flags="options"? + * byline="true|false"? > + * regularexpression? + * substitution? + * fileset* + * </replaceregexp> + * + * NOTE: You must have either the file attribute specified, or at least one fileset subelement + * to operation on. You may not have the file attribute specified if you nest fileset elements + * inside this task. Also, you cannot specify both match and a regular expression subelement at + * the same time, nor can you specify the replace attribute and the substitution subelement at + * the same time. + * + * Attributes: + * + * file --> A single file to operation on (mutually exclusive with the fileset subelements) + * match --> The Perl5 Regular expression to match (see perl5 documentation) + * replace --> The Perl5 Expression replacement string (see perl5 documentation) + * flags --> The Perl5 options to give to the replacement (see perl5 documentation for full list) + * g = Substitute all occurrences. default is to replace only the first one + * i = Case insensitive match + * + * byline --> Should this file be processed a single line at a time (default is false) + * "true" indicates to perform replacement on a line by line basis + * "false" indicates to perform replacement on the whole file at once. + * + * Example: + * + * The following call could be used to replace an old property name in a ".properties" + * file with a new name. In the replace attribute, you can refer to any part of the + * match expression in parenthesis using the syntax appropriate for the specified + * implementation ('$$1' for org.apache.tools.ant.util.regexp.JakartaOroRegexp). + * + * <replaceregexp file="test.properties" + * match="MyProperty=(.*)" + * replace="NewProperty=$$1" + * byline="true" /> + * + *
+ * For jdk <= 1.3, there are two available implementations: + * org.apache.tools.ant.util.regexp.JakartaOroRegexp (the default) + * Based on the jakarta-oro package + * + * org.apache.tools.ant.util.regexp.JakartaRegexpRegexp + * Based on the jakarta-regexp package + * + * For jdk <= 1.4, and additional implementation is available: + * org.apache.tools.ant.util.regexp.Jdk14RegexpRegexp + * Based on the jdk 1.4 built in regular expression package. + *+ * + * @see org.apache.oro.regex.Perl5Compiler + * @see org.apache.regexp.RE + * @see java.util.regex.Pattern + * + *
+ * <regularexpression [ [id="id"] pattern="expression" | refid="id" ] + * /> + *+ * + * @see org.apache.tools.ant.util.regexp.Regexp + * @author Matthew Inger mattinger@mindless.com + */ +public class RegularExpression extends DataType +{ + public static final String DATA_TYPE_NAME = "regularexpression"; + + // The regular expression factory + private static final RegexpFactory factory = new RegexpFactory(); + + private Regexp regexp; + + public RegularExpression() + { + this.regexp = factory.newRegexp(); + } + + public void setPattern(String pattern) + { + this.regexp.setPattern(pattern); + } + + /*** + * Gets the pattern string for this RegularExpression in the + * given project. + */ + public String getPattern(Project p) + { + if (isReference()) + return getRef(p).getPattern(p); + + return regexp.getPattern(); + } + + public Regexp getRegexp(Project p) + { + if (isReference()) + return getRef(p).getRegexp(p); + return this.regexp; + } + + /*** + * Get the RegularExpression this reference refers to in + * the given project. Check for circular references too + */ + public RegularExpression getRef(Project p) + { + if (!checked) + { + Stack stk = new Stack(); + stk.push(this); + dieOnCircularReference(stk, p); + } + + + Object o = ref.getReferencedObject(p); + if (!(o instanceof RegularExpression)) + { + String msg = ref.getRefId() + " doesn\'t denote a regularexpression"; + throw new BuildException(msg); + } + else + { + return (RegularExpression) o; + } + } + +} diff --git a/src/main/org/apache/tools/ant/types/Substitution.java b/src/main/org/apache/tools/ant/types/Substitution.java new file mode 100644 index 000000000..ebb817ac5 --- /dev/null +++ b/src/main/org/apache/tools/ant/types/Substitution.java @@ -0,0 +1,129 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *
+ * <substitition [ [id="id"] expression="expression" | refid="id" ] + * /> + *+ * + * @author Matthew Inger mattinger@mindless.com + */ +public class Substitution extends DataType +{ + public static final String DATA_TYPE_NAME = "substitition"; + + private String expression; + + public Substitution() + { + this.expression = null; + } + + public void setExpression(String expression) + { + this.expression = expression; + } + + /*** + * Gets the pattern string for this RegularExpression in the + * given project. + */ + public String getExpression(Project p) + { + if (isReference()) + return getRef(p).getExpression(p); + + return expression; + } + + /*** + * Get the RegularExpression this reference refers to in + * the given project. Check for circular references too + */ + public Substitution getRef(Project p) + { + if (!checked) + { + Stack stk = new Stack(); + stk.push(this); + dieOnCircularReference(stk, p); + } + + + Object o = ref.getReferencedObject(p); + if (!(o instanceof Substitution)) + { + String msg = ref.getRefId() + " doesn\'t denote a substitution"; + throw new BuildException(msg); + } + else + { + return (Substitution) o; + } + } + +} diff --git a/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java b/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java index c2baf248e..866bdf6db 100644 --- a/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java +++ b/src/main/org/apache/tools/ant/util/regexp/JakartaOroMatcher.java @@ -54,45 +54,77 @@ package org.apache.tools.ant.util.regexp; -import org.apache.oro.text.regex.*; - import org.apache.tools.ant.BuildException; +import org.apache.oro.text.regex.MatchResult; +import org.apache.oro.text.regex.Pattern; +import org.apache.oro.text.regex.Perl5Compiler; +import org.apache.oro.text.regex.Perl5Matcher; +import org.apache.oro.text.regex.Perl5Pattern; +import org.apache.oro.text.regex.Util; + import java.util.Vector; /** * Implementation of RegexpMatcher for Jakarta-ORO. * * @author Stefan Bodewig + * @author Matthew Inger */ public class JakartaOroMatcher implements RegexpMatcher { - protected Perl5Matcher reg = new Perl5Matcher(); - protected Perl5Compiler comp = new Perl5Compiler(); - private Pattern pattern; + private String pattern; + protected final Perl5Compiler compiler = new Perl5Compiler(); + protected final Perl5Matcher matcher = new Perl5Matcher(); + + public JakartaOroMatcher() {} /** * Set the regexp pattern from the String description. */ - public void setPattern(String pattern) throws BuildException { - try { - this.pattern = comp.compile(pattern); - } catch (MalformedPatternException e) { - throw new BuildException(e); - } + public void setPattern(String pattern) { + this.pattern = pattern; } /** * Get a String representation of the regexp pattern */ public String getPattern() { - return pattern.getPattern(); + return this.pattern; + } + + /** + * Get a compiled representation of the regexp pattern + */ + protected Pattern getCompiledPattern(int options) + throws BuildException + { + try + { + // compute the compiler options based on the input options first + Pattern p = compiler.compile(pattern, getCompilerOptions(options)); + return p; + } + catch (Exception e) + { + throw new BuildException(e); + } } /** * Does the given argument match the pattern? */ - public boolean matches(String argument) { - return reg.contains(argument, pattern); + public boolean matches(String argument) throws BuildException { + return matches(argument, MATCH_DEFAULT); + } + + /** + * Does the given argument match the pattern? + */ + public boolean matches(String input, int options) + throws BuildException + { + Pattern p = getCompiledPattern(options); + return matcher.contains(input, p); } /** @@ -101,16 +133,46 @@ public class JakartaOroMatcher implements RegexpMatcher { *
Group 0 will be the full match, the rest are the * parenthesized subexpressions
. */ - public Vector getGroups(String argument) { - if (!matches(argument)) { + public Vector getGroups(String argument) throws BuildException { + return getGroups(argument, MATCH_DEFAULT); + } + + /** + * Returns a Vector of matched groups found in the argument. + * + *Group 0 will be the full match, the rest are the + * parenthesized subexpressions
. + */ + public Vector getGroups(String input, int options) + throws BuildException + { + if (!matches(input, options)) { return null; } Vector v = new Vector(); - MatchResult mr = reg.getMatch(); - for (int i=0; iGroup 0 will be the full match, the rest are the * parenthesized subexpressions
. */ - public Vector getGroups(String argument) { - if (!matches(argument)) { + public Vector getGroups(String argument) throws BuildException { + return getGroups(argument, MATCH_DEFAULT); + } + + public Vector getGroups(String input, int options) + throws BuildException + { + RE reg = getCompiledPattern(options); + if (!matches(input, reg)) { return null; } Vector v = new Vector(); - for (int i=0; iGroup 0 will be the full match, the rest are the * parenthesized subexpressions
. */ - public Vector getGroups(String argument) { - Matcher matcher = pattern.matcher(argument); + public Vector getGroups(String argument) throws BuildException { + return getGroups(argument, MATCH_DEFAULT); + } + + /** + * Returns a Vector of matched groups found in the argument. + * + *Group 0 will be the full match, the rest are the + * parenthesized subexpressions
. + */ + public Vector getGroups(String input, int options) + throws BuildException + { + Pattern p = getCompiledPattern(options); + Matcher matcher = p.matcher(input); if (!matcher.find()) { return null; } Vector v = new Vector(); - for (int i=0; i<=matcher.groupCount(); i++) { + int cnt = matcher.groupCount(); + for (int i=0; i<=cnt; i++) { v.addElement(matcher.group(i)); } return v; } + protected int getCompilerOptions(int options) + { + int cOptions = 0; + + if (RegexpUtil.hasFlag(options, MATCH_CASE_INSENSITIVE)) + cOptions |= Pattern.CASE_INSENSITIVE; + if (RegexpUtil.hasFlag(options, MATCH_MULTILINE)) + cOptions |= Pattern.MULTILINE; + if (RegexpUtil.hasFlag(options, MATCH_SINGLELINE)) + cOptions |= Pattern.DOTALL; + + return cOptions; + } + } diff --git a/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexp.java b/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexp.java new file mode 100644 index 000000000..0c5a584d1 --- /dev/null +++ b/src/main/org/apache/tools/ant/util/regexp/Jdk14RegexpRegexp.java @@ -0,0 +1,106 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *ant.regexp.regexpimpl
.
+ *
+ * @author Matthew Inger mattinger@mindless.com
+ */
+public class RegexpFactory extends RegexpMatcherFactory
+{
+ public RegexpFactory()
+ {
+ }
+
+ /***
+ * Create a new regular expression matcher instance.
+ */
+ public Regexp newRegexp() throws BuildException {
+ return (Regexp) newRegexp(null);
+ }
+
+ /***
+ * Create a new regular expression matcher instance.
+ *
+ * @param p Project whose ant.regexp.regexpimpl property will be used.
+ */
+ public Regexp newRegexp(Project p) throws BuildException {
+ String systemDefault = null;
+ if (p == null) {
+ systemDefault = System.getProperty("ant.regexp.regexpimpl");
+ } else {
+ systemDefault = (String) p.getProperties().get("ant.regexp.regexpimpl");
+ }
+
+ if (systemDefault != null) {
+ return (Regexp)createInstance(systemDefault);
+ // XXX should we silently catch possible exceptions and try to
+ // load a different implementation?
+ }
+
+ try {
+ return (Regexp)createInstance("org.apache.tools.ant.util.regexp.Jdk14RegexpRegexp");
+ } catch (BuildException be) {}
+
+ try {
+ return (Regexp)createInstance("org.apache.tools.ant.util.regexp.JakartaOroRegexp");
+ } catch (BuildException be) {}
+
+ try {
+ return (Regexp)createInstance("org.apache.tools.ant.util.regexp.JakartaRegexpRegexp");
+ } catch (BuildException be) {}
+
+ throw new BuildException("No supported regular expression matcher found");
+ }
+
+}
diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java
index 398a48355..fc424f7b1 100644
--- a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java
+++ b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcher.java
@@ -61,9 +61,42 @@ import java.util.Vector;
* Interface describing a regular expression matcher.
*
* @author Stefan Bodewig
+ * @author Matthew Inger
*/
public interface RegexpMatcher {
+ /***
+ * Replace only the first occurance of the regular expression
+ */
+ int REPLACE_FIRST = 0x00000001;
+
+ /***
+ * Replace all occurances of the regular expression
+ */
+ int REPLACE_ALL = 0x00000010;
+
+ /***
+ * Default Mask (case insensitive, neither multiline nor
+ * singleline specified).
+ */
+ int MATCH_DEFAULT = 0x00000000;
+
+ /***
+ * Perform a case insenstive match
+ */
+ int MATCH_CASE_INSENSITIVE = 0x00000100;
+
+ /***
+ * Treat the input as a multiline input
+ */
+ int MATCH_MULTILINE = 0x00001000;
+
+ /***
+ * Treat the input as singleline input ('.' matches newline)
+ */
+ int MATCH_SINGLELINE = 0x00010000;
+
+
/**
* Set the regexp pattern from the String description.
*/
@@ -72,12 +105,12 @@ public interface RegexpMatcher {
/**
* Get a String representation of the regexp pattern
*/
- String getPattern();
+ String getPattern() throws BuildException;
/**
* Does the given argument match the pattern?
*/
- boolean matches(String argument);
+ boolean matches(String argument) throws BuildException;
/**
* Returns a Vector of matched groups found in the argument.
@@ -85,5 +118,24 @@ public interface RegexpMatcher {
* Group 0 will be the full match, the rest are the * parenthesized subexpressions
. */ - Vector getGroups(String argument); + Vector getGroups(String argument) throws BuildException; + + /*** + * Does this regular expression match the input, given + * certain options + * @param input The string to check for a match + * @param options The list of options for the match. See the + * MATCH_ constants above. + */ + boolean matches(String input, int options) throws BuildException; + + /*** + * Get the match groups from this regular expression. The return + * type of the elements is always String. + * @param input The string to check for a match + * @param options The list of options for the match. See the + * MATCH_ constants above. + */ + Vector getGroups(String input, int options) throws BuildException; + } diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java index f5f9093b4..e6bc34a83 100644 --- a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java +++ b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java @@ -55,6 +55,7 @@ package org.apache.tools.ant.util.regexp; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; /** * Simple Factory Class that produces an implementation of @@ -71,11 +72,30 @@ public class RegexpMatcherFactory { public RegexpMatcherFactory() {} + /*** + * Create a new regular expression instance. + */ public RegexpMatcher newRegexpMatcher() throws BuildException { - String systemDefault = System.getProperty("ant.regexp.matcherimpl"); + return newRegexpMatcher(null); + } + + /*** + * Create a new regular expression instance. + * + * @param p Project whose ant.regexp.regexpimpl property will be used. + */ + public RegexpMatcher newRegexpMatcher(Project p) + throws BuildException { + String systemDefault = null; + if (p == null) { + systemDefault = System.getProperty("ant.regexp.regexpimpl"); + } else { + systemDefault = (String) p.getProperties().get("ant.regexp.regexpimpl"); + } + if (systemDefault != null) { return createInstance(systemDefault); - // XXX should we silently possible exceptions and try to + // XXX should we silently catch possible exceptions and try to // load a different implementation? } diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpUtil.java b/src/main/org/apache/tools/ant/util/regexp/RegexpUtil.java new file mode 100644 index 000000000..3e4654427 --- /dev/null +++ b/src/main/org/apache/tools/ant/util/regexp/RegexpUtil.java @@ -0,0 +1,72 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *