You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Thorsten Möller <Th...@web.de> on 2003/09/05 20:18:21 UTC

donate a new selector

Hi,

I wrote a new selector named "ContainsRegexpSelector". It works pretty much
the same like the "ContainsSelector" except that it uses a regular
expression to decide wheter including a file in a particular fileset.
Because I think there is a commond need for such a selector I would donate
the code to the Ant project. I did not test the code very exhaustive but I
think it works ok (the code is mostly a composition from different Ant
classes, i.e. I copied a lot  Also there is no documentation except the
Java Doc comments.

At the end you will find the code.

I would be very pleased to see the selector as a "normal" part in the
project some day.

Thorsten Möller


-------------------------------------------
/*
 * Created on 05.09.2003
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2002 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 "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
 * <http://www.apache.org/>.
 */

package org.apache.tools.ant.types.selectors;

import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import org.apache.tools.ant.types.Parameter;
import org.apache.tools.ant.types.selectors.BaseExtendSelector;
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 whether they contain a
 * particular pattern expressed with a regular expression.
 *
 * Note: This class was directly copied from the Apache Ant project
 * <code>org.apache.tools.ant.types.selectors.ContainsSelector</code>
 * class. This results in the Apache reference at the beginning of
 * this file.
 *
 * @author Thorsten Möller - Thorsten.Moeller@jexam.de
 *
 * $Revision: $; $Author: $; $Date: $
 */
public class ContainsRegexpSelector extends BaseExtendSelector
{

 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, executing the replacement
  * on one line at a time.  This is useful if you
  * want to only replace 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>g : Global replacement.  Replace all occurences found
  *  <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
   {
    int flen = (int) file.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;
    }
    if (regexp.matches(new String(tmpBuf), 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;
 }
}

Re: donate a new selector

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On Tuesday, September 9, 2003, at 11:10  AM, Thorsten Möller wrote:
> Erik Hatcher <er...@ehatchersolutions.com> wrote:
>> There already is a <containsregexp> in the latest version of Ant.
> Uups, I didn't see this because I only worked with Ant 1.5.x.

Always best to check with the latest codebase when adding new features 
:)

> I have attached a file "patch.txt" generated by CVS rdiff (patch).

Your patch was not diffed against anything.  Could you diff against the 
lastest CVS version and then enter your patch as a Bugzilla enhancement 
request?

Thanks,
	Erik


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Re: donate a new selector

Posted by Thorsten Möller <Th...@web.de>.
Erik Hatcher <er...@ehatchersolutions.com> wrote:
> There already is a <containsregexp> in the latest version of Ant.
Uups, I didn't see this because I only worked with Ant 1.5.x.

>  I'm
> not sure how the implementations compare.  Could you compare yours
> with it and offer any benefits yours has as a patch against the HEAD
> version of Ant's codebase?
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 have attached a file "patch.txt" generated by CVS rdiff (patch).

Thorsten

Re: donate a new selector

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
There already is a <containsregexp> in the latest version of Ant.  I'm 
not sure how the implementations compare.  Could you compare yours with 
it and offer any benefits yours has as a patch against the HEAD version 
of Ant's codebase?

	Erik


On Friday, September 5, 2003, at 02:18  PM, Thorsten Möller wrote:

> Hi,
>
> I wrote a new selector named "ContainsRegexpSelector". It works pretty 
> much
> the same like the "ContainsSelector" except that it uses a regular
> expression to decide wheter including a file in a particular fileset.
> Because I think there is a commond need for such a selector I would 
> donate
> the code to the Ant project. I did not test the code very exhaustive 
> but I
> think it works ok (the code is mostly a composition from different Ant
> classes, i.e. I copied a lot  Also there is no documentation except the
> Java Doc comments.
>
> At the end you will find the code.
>
> I would be very pleased to see the selector as a "normal" part in the
> project some day.
>
> Thorsten Möller
>
>
> -------------------------------------------
> /*
>  * Created on 05.09.2003
>  *
>  * The Apache Software License, Version 1.1
>  *
>  * Copyright (c) 2002 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 "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
>  * <http://www.apache.org/>.
>  */
>
> package org.apache.tools.ant.types.selectors;
>
> import java.io.File;
> import java.io.BufferedReader;
> import java.io.FileReader;
> import java.io.IOException;
>
> import org.apache.tools.ant.types.Parameter;
> import org.apache.tools.ant.types.selectors.BaseExtendSelector;
> 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 whether they contain a
>  * particular pattern expressed with a regular expression.
>  *
>  * Note: This class was directly copied from the Apache Ant project
>  * <code>org.apache.tools.ant.types.selectors.ContainsSelector</code>
>  * class. This results in the Apache reference at the beginning of
>  * this file.
>  *
>  * @author Thorsten Möller - Thorsten.Moeller@jexam.de
>  *
>  * $Revision: $; $Author: $; $Date: $
>  */
> public class ContainsRegexpSelector extends BaseExtendSelector
> {
>
>  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, executing the replacement
>   * on one line at a time.  This is useful if you
>   * want to only replace 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>g : Global replacement.  Replace all occurences found
>   *  <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
>    {
>     int flen = (int) file.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;
>     }
>     if (regexp.matches(new String(tmpBuf), 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