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 [EMAIL PROTECTED]
 *
 * 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 - [EMAIL PROTECTED]
 *
 * $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;
 }
}

Reply via email to