You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bu...@apache.org on 2003/09/09 19:12:45 UTC

DO NOT REPLY [Bug 23037] New: - enhancement of org.apache.tools.ant.types.selectors.ContainsRegexpSelector

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: dev@ant.apache.org
        ReportedBy: ThorstenMoeller@web.de


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  &lt;= 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:jvandermeer2@comcast.net">Jay van der Meer</a>
- * @since Ant 1.6
+ * For jdk &gt;= 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 --&gt; The Regular expression to search for
+ *     flags   --&gt; 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  --&gt; 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 - Thorsten.Moeller@jexam.de
+ * 
+ * $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: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org