DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23037>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23037 enhancement of org.apache.tools.ant.types.selectors.ContainsRegexpSelector Summary: enhancement of org.apache.tools.ant.types.selectors.ContainsRegexpSelec tor Product: Ant Version: 1.6Alpha (nightly) Platform: All OS/Version: All Status: NEW Severity: Enhancement Priority: Other Component: Other AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] I wrote a little extension to the ContainsRegexpSelector. Like the <replaceregexp> Task (org.apache.tools.ant.taskdefs.optional.ReplaceRegExp) the selector supports two additional parameters: "byline" and "flags". You will find a short documentation inside the JavaDoc comments. I want to donate the code to the project. Thorsten Möller Here is the CVS patch generated against the Head-Version: --------------------------------------------------------- Index: ContainsRegexpSelector.java =================================================================== RCS file: /home/cvspublic/ant/src/main/org/apache/tools/ant/types/selectors/Contain sRegexpSelector.java,v retrieving revision 1.5 diff -u -r1.5 ContainsRegexpSelector.java --- ContainsRegexpSelector.java 29 Jul 2003 08:37:18 -0000 1.5 +++ ContainsRegexpSelector.java 9 Sep 2003 17:04:35 -0000 @@ -54,140 +54,322 @@ package org.apache.tools.ant.types.selectors; -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; +import java.io.BufferedReader; +import java.io.FileReader; import java.io.IOException; -import java.io.InputStreamReader; -import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.Parameter; -import org.apache.tools.ant.types.RegularExpression; +import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.regexp.Regexp; +import org.apache.tools.ant.util.regexp.RegexpFactory; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; /** - * Selector that filters files based on a regular expression. + * Selector that filters files based on whether they contain a + * particular pattern expressed with a regular expression. + * The input file(s) must be able to be properly processed by + * a Reader instance. That is, it must be text only, no binary. + * + * The syntax of the regular expression depends on the implemtation that + * you choose to use. The system property <code>ant.regexp.regexpimpl</code> + * will be the classname of the implementation that will be used (the default + * is <code>org.apache.tools.ant.util.regexp.JakartaOroRegexp</code> and + * requires the Jakarta Oro Package). + * + * <pre> + * 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 * - * @author <a href="mailto:[EMAIL PROTECTED]">Jay van der Meer</a> - * @since Ant 1.6 + * For jdk >= 1.4 an additional implementation is available: + * org.apache.tools.ant.util.regexp.Jdk14RegexpRegexp + * Requires the jdk 1.4 built in regular expression package. + * + * Attributes: + * + * pattern --> The Regular expression to search for + * flags --> The options to give to the search. For more information, consult the Perl5 syntax. + * i = Case insensitive match + * m = Multiline. Treat the string as multiple lines of input, using + * "^" and "$" as the start or end of any line, respectively, rather + * than start or end of string. + * m = Singleline. Treat the string as a single line of input, using + * "." to match any character, including a newline, which normally, + * it would not match. + * + * byline --> Should files be processed a single line at a time (default is false) + * "true" indicates to perform search on a line by line basis + * "false" indicates to perform search on the whole file at once. + * + * + * @author Thorsten Möller - [EMAIL PROTECTED] + * + * $Revision: $; $Author: $; $Date: $ */ -public class ContainsRegexpSelector extends BaseExtendSelector { +public class ContainsRegexpSelector extends BaseExtendSelector +{ - private String userProvidedExpression = null; - private RegularExpression myRegExp = null; - private Regexp myExpression = null; - /** Key to used for parameterized custom selector */ - public static final String EXPRESSION_KEY = "expression"; - - /** - * Creates a new <code>ContainsRegexpSelector</code> instance. - */ - public ContainsRegexpSelector() { - } - - /** - * @return a string describing this object - */ - public String toString() { - StringBuffer buf = new StringBuffer( - "{containsregexpselector expression: "); - buf.append(userProvidedExpression); - buf.append("}"); - return buf.toString(); - } - - /** - * The regular expression used to search the file. - * - * @param theexpression this must match a line in the file to be selected. - */ - public void setExpression(String theexpression) { - this.userProvidedExpression = theexpression; - } - - /** - * When using this as a custom selector, this method will be called. - * It translates each parameter into the appropriate setXXX() call. - * - * @param parameters the complete set of parameters for this selector - */ - public void setParameters(Parameter[] parameters) { - super.setParameters(parameters); - if (parameters != null) { - for (int i = 0; i < parameters.length; i++) { - String paramname = parameters[i].getName(); - if (EXPRESSION_KEY.equalsIgnoreCase(paramname)) { - setExpression(parameters[i].getValue()); - } else { - setError("Invalid parameter " + paramname); - } - } - } - } - - /** - * Checks that an expression was specified. - * - */ - public void verifySettings() { - if (userProvidedExpression == null) { - setError("The expression attribute is required"); - } - } - - /** - * Tests a regular expression against each line of text in the file. - * - * @param basedir the base directory the scan is being done from - * @param filename is the name of the file to check - * @param file is a java.io.File object the selector can use - * @return whether the file should be selected or not - */ - public boolean isSelected(File basedir, String filename, File file) { - String teststr = null; - BufferedReader in = null; - - // throw BuildException on error - - validate(); - - if (file.isDirectory()) { - return true; - } - - if (myRegExp == null) { - myRegExp = new RegularExpression(); - myRegExp.setPattern(userProvidedExpression); - myExpression = myRegExp.getRegexp(getProject()); - } - - try { - in = new BufferedReader(new InputStreamReader( - new FileInputStream(file))); - - teststr = in.readLine(); - - while (teststr != null) { - - if (myExpression.matches(teststr)) { - return true; - } - teststr = in.readLine(); - } - - return false; - } catch (IOException ioe) { - throw new BuildException("Could not read file " + filename); - } finally { - if (in != null) { - try { - in.close(); - } catch (Exception e) { - throw new BuildException("Could not close file " - + filename); - } - } - } - } + private boolean byline; + private String flags; + private Regexp regexp = null; + private static final RegexpFactory factory = new RegexpFactory(); + + public static final String PATTERN_KEY = "pattern"; + public static final String FLAGS_KEY = "flags"; + public static final String BYLINE_KEY = "byline"; + + public ContainsRegexpSelector() + { + this.regexp = factory.newRegexp(); + } + + public String toString() + { + StringBuffer buf = new StringBuffer("{containsRegexpSelector pattern: "); + buf.append(regexp.getPattern()); + buf.append(" byline: "); + buf.append(Boolean.toString(byline)); + buf.append(" flags: "); + buf.append(flags); + buf.append("}"); + return buf.toString(); + } + + /** + * Process the file(s) one line at a time. + * This is useful if you want to only search for the first occurence of a regular expression on + * each line, which is not easy to do when processing the file as a whole. + * Defaults to <i>false</i>.</td> + */ + public void setByLine(String byline) + { + Boolean res = Boolean.valueOf(byline); + if (res == null) + { + res = Boolean.FALSE; + } + this.byline = res.booleanValue(); + } + + /** + * The flags to use when matching the regular expression. For more + * information, consult the Perl5 syntax. + * <ul> + * <li>i : Case Insensitive. Do not consider case in the match + * <li>m : Multiline. Treat the string as multiple lines of input, + * using "^" and "$" as the start or end of any line, respectively, rather than start or end of string. + * <li>s : Singleline. Treat the string as a single line of input, using + * "." to match any character, including a newline, which normally, it would not match. + *</ul> + */ + public void setFlags(String flags) + { + this.flags = flags; + } + + /** + * The pattern to search for within a file. + * + * @param regexp the string that a file must contain to be selected. + */ + public void setRegexp(String pattern) + { + this.regexp.setPattern(pattern); + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param parameters the complete set of parameters for this selector + */ + public void setParameters(Parameter[] parameters) + { + super.setParameters(parameters); + if (parameters != null) + { + for (int i = 0; i < parameters.length; i++) + { + String paramname = parameters[i].getName(); + if (PATTERN_KEY.equalsIgnoreCase(paramname)) + { + setRegexp(parameters[i].getValue()); + } + else if (BYLINE_KEY.equalsIgnoreCase (paramname)) + { + setByLine(parameters[i].getValue()); + } + else if (FLAGS_KEY.equalsIgnoreCase(paramname)) + { + setFlags(parameters[i].getValue()); + } + else + { + setError("Invalid parameter " + paramname); + } + } + } + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the pattern attribute has been set. + * + */ + public void verifySettings() + { + if (regexp == null) + { + setError("The pattern attribute is required"); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a java.io.File object the selector can use + * @return whether the file should be selected or not + */ + public boolean isSelected(File basedir, String filename, File file) + { + + // throw BuildException on error + validate(); + + if (file.isDirectory()) + { + return true; + } + + 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; + + FileReader r = null; + try + { + r = new FileReader(file); + BufferedReader br = new BufferedReader(r); + log( + "Searching pattern '" + + regexp.getPattern() + + "' in '" + + file.getPath() + + "'" + + (byline ? " by line" : "") + + (flags.length() > 0 ? " with flags: '" + flags + "'" : "") + + ".", + Project.MSG_VERBOSE); + + if (byline) + { + StringBuffer linebuf = new StringBuffer(); + String line = null; + int c; + boolean hasCR = false; + + do + { + c = br.read(); + if (c == '\r') + { + if (hasCR) + { + // second CR -> EOL + possibly empty line + line = linebuf.toString (); + if (regexp.matches (line, options)) + { + return true; + } + linebuf.setLength(0); + // hasCR is still true (for the second one) + } + else + { + // first CR in this line + hasCR = true; + } + } + else if (c == '\n') + { + // LF -> EOL + line = linebuf.toString(); + if (regexp.matches(line, options)) + { + return true; + } + if (hasCR) + { + hasCR = false; + } + linebuf.setLength(0); + } + else + { // any other char + if ((hasCR) || (c < 0)) + { + // Mac-style linebreak or EOF (or both) + line = linebuf.toString (); + if (regexp.matches (line, options)) + { + return true; + } + if (hasCR) + { + hasCR = false; + } + linebuf.setLength(0); + } + if (c >= 0) + { + linebuf.append((char) c); + } + } + } + while (c >= 0); + } + else + { + String buf = FileUtils.readFully(br); + if (regexp.matches(buf, options)) + { + return true; + } + } + r.close(); + r = null; + } + catch (IOException ioe) + { + throw new BuildException("Could not read file " + filename); + } + finally + { + try + { + if (r != null) + { + r.close(); + } + } + catch (Exception e) + { + throw new BuildException("Could not close file " + filename); + } + } + return false; + } } - --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]