ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From umag...@apache.org
Subject cvs commit: jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/types FileSet.java Pattern.java PatternSet.java ZipScanner.java
Date Sun, 27 Jan 2002 02:10:43 GMT
umagesh     02/01/26 18:10:43

  Added:       proposal/sandbox/selectors README
               proposal/sandbox/selectors/src/main/org/apache/tools/ant
                        DirectoryScanner.java FileScanner.java
               proposal/sandbox/selectors/src/main/org/apache/tools/ant/selectors
                        FileSelector.java FileTypeSelector.java
                        defaults.properties
               proposal/sandbox/selectors/src/main/org/apache/tools/ant/types
                        FileSet.java Pattern.java PatternSet.java
                        ZipScanner.java
  Log:
  Ant1 compatible Selector API Implementation.
  
  Revision  Changes    Path
  1.1                  jakarta-ant/proposal/sandbox/selectors/README
  
  Index: README
  ===================================================================
  Selector API
  ============
  
  Currently our filesets allow us to select a set of files based on name patterns.
  For instance we could create a set of all the files that end with ".java". 
  However there are cases when you wish to select files based on their other 
  attributes, such as if they are read only or if they are older than a specified 
  date etc. 
  
  The selector API is one such mechanism to do this. The selector API will allow 
  you to build file sets based on criteria other than name. Some possible criteria 
  would be 
  
  Is the file readable? 
  Is the file writeable? 
  What date was the file modified on? 
  What size is the file? 
  Does the contents contain the string "magic"? 
  
  If we end up supporting a VFS then we could expand the number of selectors 
  considerably. A mock representation that has been proposed before is the 
  following. Of course this is subject to change as soon as someone wants to 
  tackle this action ;) 
  
   <include name="**/*.java">
     <selector type="permission" value="r"/>
  
     <!-- could optionally be directory/or some other system specific features -->
     <selector type="type" value="file"/> 
     <selector type="modify-time" 
               operation="greater-than" 
               value="29th Feb 2003"/>
   </include>
  
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/DirectoryScanner.java
  
  Index: DirectoryScanner.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-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 "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
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant;
  
  import java.io.File;
  import java.io.InputStream;
  import java.io.IOException;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Vector;
  import java.util.Properties;
  import java.util.StringTokenizer;
  import org.apache.tools.ant.types.PatternSet;
  import org.apache.tools.ant.types.Pattern;
  import org.apache.tools.ant.selectors.FileSelector;
  
  /**
   * Class for scanning a directory for files/directories that match a certain
   * criteria.
   * <p>
   * These criteria consist of a set of include and exclude patterns. With these
   * patterns, you can select which files you want to have included, and which
   * files you want to have excluded.
   * <p>
   * The idea is simple. A given directory is recursively scanned for all files
   * and directories. Each file/directory is matched against a set of include
   * and exclude patterns. Only files/directories that match at least one
   * pattern of the include pattern list, and don't match a pattern of the
   * exclude pattern list will be placed in the list of files/directories found.
   * <p>
   * When no list of include patterns is supplied, "**" will be used, which
   * means that everything will be matched. When no list of exclude patterns is
   * supplied, an empty list is used, such that nothing will be excluded.
   * <p>
   * The pattern matching is done as follows:
   * The name to be matched is split up in path segments. A path segment is the
   * name of a directory or file, which is bounded by
   * <code>File.separator</code> ('/' under UNIX, '\' under Windows).
   * E.g. "abc/def/ghi/xyz.java" is split up in the segments "abc", "def", "ghi"
   * and "xyz.java".
   * The same is done for the pattern against which should be matched.
   * <p>
   * Then the segments of the name and the pattern will be matched against each
   * other. When '**' is used for a path segment in the pattern, then it matches
   * zero or more path segments of the name.
   * <p>
   * There are special case regarding the use of <code>File.separator</code>s at
   * the beginningof the pattern and the string to match:<br>
   * When a pattern starts with a <code>File.separator</code>, the string
   * to match must also start with a <code>File.separator</code>.
   * When a pattern does not start with a <code>File.separator</code>, the
   * string to match may not start with a <code>File.separator</code>.
   * When one of these rules is not obeyed, the string will not
   * match.
   * <p>
   * When a name path segment is matched against a pattern path segment, the
   * following special characters can be used:
   * '*' matches zero or more characters,
   * '?' matches one character.
   * <p>
   * Examples:
   * <p>
   * "**\*.class" matches all .class files/dirs in a directory tree.
   * <p>
   * "test\a??.java" matches all files/dirs which start with an 'a', then two
   * more characters and then ".java", in a directory called test.
   * <p>
   * "**" matches everything in a directory tree.
   * <p>
   * "**\test\**\XYZ*" matches all files/dirs that start with "XYZ" and where
   * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123").
   * <p>
   * Case sensitivity may be turned off if necessary.  By default, it is
   * turned on.
   * <p>
   * Example of usage:
   * <pre>
   *   String[] includes = {"**\\*.class"};
   *   String[] excludes = {"modules\\*\\**"};
   *   ds.setIncludes(includes);
   *   ds.setExcludes(excludes);
   *   ds.setBasedir(new File("test"));
   *   ds.setCaseSensitive(true);
   *   ds.scan();
   *
   *   System.out.println("FILES:");
   *   String[] files = ds.getIncludedFiles();
   *   for (int i = 0; i < files.length;i++) {
   *     System.out.println(files[i]);
   *   }
   * </pre>
   * This will scan a directory called test for .class files, but excludes all
   * .class files in all directories under a directory called "modules"
   *
   * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
   * @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a>
   */
  public class DirectoryScanner implements FileScanner {
  
      /**
       * Patterns that should be excluded by default.
       *
       * @see #addDefaultExcludes()
       */
      protected final static String[] DEFAULTEXCLUDES = {
          "**/*~",
          "**/#*#",
          "**/.#*",
          "**/%*%",
          "**/CVS",
          "**/CVS/**",
          "**/.cvsignore",
          "**/SCCS",
          "**/SCCS/**",
          "**/vssver.scc"
      };
  
      /**
       * The base directory which should be scanned.
       */
      protected File basedir;
  
      /**
       * The patterns for the files that should be included.
       */
      protected Pattern[] includes;
  
      /**
       * The patterns for the files that should be excluded.
       */
      protected Pattern[] excludes;
  
      /**
       * The files that where found and matched at least one includes, and matched
       * no excludes.
       */
      protected Vector filesIncluded;
  
      /**
       * The files that where found and did not match any includes.
       */
      protected Vector filesNotIncluded;
  
      /**
       * The files that where found and matched at least one includes, and also
       * matched at least one excludes.
       */
      protected Vector filesExcluded;
  
      /**
       * The directories that where found and matched at least one includes, and
       * matched no excludes.
       */
      protected Vector dirsIncluded;
  
      /**
       * The directories that where found and did not match any includes.
       */
      protected Vector dirsNotIncluded;
  
      /**
       * The files that where found and matched at least one includes, and also
       * matched at least one excludes.
       */
      protected Vector dirsExcluded;
  
      /**
       * Have the Vectors holding our results been built by a slow scan?
       */
      protected boolean haveSlowResults = false;
  
      /**
       * Should the file system be treated as a case sensitive one?
       */
      protected boolean isCaseSensitive = true;
  
      /**
       * Is everything we've seen so far included?
       */
      protected boolean everythingIncluded = true;
  
      private static Hashtable selectorClasses = null;
  
      static {
          String defs = "/org/apache/tools/ant/selectors/defaults.properties";
          selectorClasses = new Hashtable();
  
          try {
              Properties props = new Properties();
              InputStream in = DirectoryScanner.class.getResourceAsStream(defs);
              if (in == null) {
                  throw new BuildException("Can't load default selector list");
              }
              props.load(in);
              in.close();
  
              Enumeration enum = props.propertyNames();
              while (enum.hasMoreElements()) {
                  String key = (String) enum.nextElement();
                  String value = props.getProperty(key);
                  try {
                      selectorClasses.put(key, Class.forName(value));
                  } catch (NoClassDefFoundError ncdfe) {
                  } catch (ClassNotFoundException cnfe) {
                  }
              }
          } catch (IOException ioe) {
              throw new BuildException("Can't load default selector list");
          }
      }
  
      /**
       * Constructor.
       */
      public DirectoryScanner() {
      }
  
  
      /**
       * Does the path match the start of this pattern up to the first "**".
       *
       * <p>This is not a general purpose test and should only be used if you
       * can live with false positives.</p>
       *
       * <p><code>pattern=**\\a</code> and <code>str=b</code> will yield true.
       *
       * @param pattern the (non-null) pattern to match against
       * @param str     the (non-null) string (path) to match
       */
      protected static boolean matchPatternStart(String pattern, String str) {
          return matchPatternStart(pattern, str, true);
      }
  
      /**
       * Does the path match the start of this pattern up to the first "**".
       *
       * <p>This is not a general purpose test and should only be used if you
       * can live with false positives.</p>
       *
       * <p><code>pattern=**\\a</code> and <code>str=b</code> will yield true.
       *
       * @param pattern             the (non-null) pattern to match against
       * @param str                 the (non-null) string (path) to match
       * @param isCaseSensitive     must matches be case sensitive?
       */
      protected static boolean matchPatternStart(String pattern, String str,
                                                 boolean isCaseSensitive) {
          // When str starts with a File.separator, pattern has to start with a
          // File.separator.
          // When pattern starts with a File.separator, str has to start with a
          // File.separator.
          if (str.startsWith(File.separator) !=
              pattern.startsWith(File.separator)) {
              return false;
          }
  
          Vector patDirs = new Vector();
          StringTokenizer st = new StringTokenizer(pattern,File.separator);
          while (st.hasMoreTokens()) {
              patDirs.addElement(st.nextToken());
          }
  
          Vector strDirs = new Vector();
          st = new StringTokenizer(str,File.separator);
          while (st.hasMoreTokens()) {
              strDirs.addElement(st.nextToken());
          }
  
          int patIdxStart = 0;
          int patIdxEnd   = patDirs.size()-1;
          int strIdxStart = 0;
          int strIdxEnd   = strDirs.size()-1;
  
          // up to first '**'
          while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
              String patDir = (String)patDirs.elementAt(patIdxStart);
              if (patDir.equals("**")) {
                  break;
              }
              if (!match(patDir,(String)strDirs.elementAt(strIdxStart), isCaseSensitive)) {
                  return false;
              }
              patIdxStart++;
              strIdxStart++;
          }
  
          if (strIdxStart > strIdxEnd) {
              // String is exhausted
              return true;
          } else if (patIdxStart > patIdxEnd) {
              // String not exhausted, but pattern is. Failure.
              return false;
          } else {
              // pattern now holds ** while string is not exhausted
              // this will generate false positives but we can live with that.
              return true;
          }
      }
  
      protected static boolean isSelected(String fileToScan, Vector selectorList) {
          boolean isInclusive = true;
          if (selectorList != null ) {
              PatternSet.SelectorEntry[] selectorEntries =
                  new PatternSet.SelectorEntry[selectorList.size()];
              selectorList.copyInto(selectorEntries);
              boolean[] selectorIndices = new boolean[selectorEntries.length];
  
              for (int i = 0; i < selectorEntries.length; i++) {
                  String type = selectorEntries[i].getType();
                  String value = selectorEntries[i].getValue();
                  String operation = selectorEntries[i].getOperation();
                  Class c = (Class) selectorClasses.get(type);
                  if (c != null) {
                      FileSelector s = null;
                      try {
                          s = (FileSelector) c.newInstance();
                          s.setValue(value);
                          s.setOperation(operation);
                          isInclusive = s.isSelected(fileToScan);
                      } catch (InstantiationException ie) {
                      } catch (IllegalAccessException ie) {
                      }
                      if (!isInclusive) {
                          break;
                      }
                  }
              }
          }
          return isInclusive;
      }
  
      /**
       * Matches a path against a pattern.
       *
       * @param pattern the (non-null) pattern to match against
       * @param str     the (non-null) string (path) to match
       *
       * @return <code>true</code> when the pattern matches against the string.
       *         <code>false</code> otherwise.
       */
      protected static boolean matchPath(String pattern, String str) {
          return matchPath(pattern, null, str, true);
      }
  
      protected static boolean matchPath(String pattern,
                                         String str, boolean isCaseSensitive) {
          return matchPath(pattern, null, str, isCaseSensitive);
      }
  
      /**
       * Matches a path against a pattern.
       *
       * @param pattern            the (non-null) pattern to match against
       * @param str                the (non-null) string (path) to match
       * @param isCaseSensitive    must a case sensitive match be done?
       *
       * @return <code>true</code> when the pattern matches against the string.
       *         <code>false</code> otherwise.
       */
      protected static boolean matchPath(String pattern, Vector selectorList,
                                         String str, boolean isCaseSensitive) {
          // When str starts with a File.separator, pattern has to start with a
          // File.separator.
          // When pattern starts with a File.separator, str has to start with a
          // File.separator.
          if (str.startsWith(File.separator) !=
              pattern.startsWith(File.separator)) {
              return false;
          }
  
          Vector patDirs = new Vector();
          StringTokenizer st = new StringTokenizer(pattern,File.separator);
          while (st.hasMoreTokens()) {
              patDirs.addElement(st.nextToken());
          }
  
          Vector strDirs = new Vector();
          st = new StringTokenizer(str,File.separator);
          while (st.hasMoreTokens()) {
              strDirs.addElement(st.nextToken());
          }
  
          int patIdxStart = 0;
          int patIdxEnd   = patDirs.size()-1;
          int strIdxStart = 0;
          int strIdxEnd   = strDirs.size()-1;
  
          // up to first '**'
          while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
              String patDir = (String)patDirs.elementAt(patIdxStart);
              if (patDir.equals("**")) {
                  break;
              }
              if (!match(patDir,(String)strDirs.elementAt(strIdxStart), isCaseSensitive)) {
                  return false;
              }
              patIdxStart++;
              strIdxStart++;
          }
          if (strIdxStart > strIdxEnd) {
              // String is exhausted
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (!patDirs.elementAt(i).equals("**")) {
                      return false;
                  }
              }
              return isSelected(str, selectorList);
          } else {
              if (patIdxStart > patIdxEnd) {
                  // String not exhausted, but pattern is. Failure.
                  return false;
              }
          }
  
          // up to last '**'
          while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
              String patDir = (String)patDirs.elementAt(patIdxEnd);
              if (patDir.equals("**")) {
                  break;
              }
              if (!match(patDir,(String)strDirs.elementAt(strIdxEnd), isCaseSensitive)) {
                  return false;
              }
              patIdxEnd--;
              strIdxEnd--;
          }
          if (strIdxStart > strIdxEnd) {
              // String is exhausted
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (!patDirs.elementAt(i).equals("**")) {
                      return false;
                  }
              }
              return isSelected(str, selectorList);
          }
  
          while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
              int patIdxTmp = -1;
              for (int i = patIdxStart+1; i <= patIdxEnd; i++) {
                  if (patDirs.elementAt(i).equals("**")) {
                      patIdxTmp = i;
                      break;
                  }
              }
              if (patIdxTmp == patIdxStart+1) {
                  // '**/**' situation, so skip one
                  patIdxStart++;
                  continue;
              }
              // Find the pattern between padIdxStart & padIdxTmp in str between
              // strIdxStart & strIdxEnd
              int patLength = (patIdxTmp-patIdxStart-1);
              int strLength = (strIdxEnd-strIdxStart+1);
              int foundIdx  = -1;
  strLoop:
              for (int i = 0; i <= strLength - patLength; i++) {
                  for (int j = 0; j < patLength; j++) {
                      String subPat = (String)patDirs.elementAt(patIdxStart+j+1);
                      String subStr = (String)strDirs.elementAt(strIdxStart+i+j);
                      if (!match(subPat,subStr, isCaseSensitive)) {
                          continue strLoop;
                      }
                  }
  
                  foundIdx = strIdxStart+i;
                  break;
              }
  
              if (foundIdx == -1) {
                  return false;
              }
  
              patIdxStart = patIdxTmp;
              strIdxStart = foundIdx+patLength;
          }
  
          for (int i = patIdxStart; i <= patIdxEnd; i++) {
              if (!patDirs.elementAt(i).equals("**")) {
                  return false;
              }
          }
  
          return isSelected(str, selectorList);
      }
  
  
      /**
       * Matches a string against a pattern. The pattern contains two special
       * characters:
       * '*' which means zero or more characters,
       * '?' which means one and only one character.
       *
       * @param pattern the (non-null) pattern to match against
       * @param str     the (non-null) string that must be matched against the
       *                pattern
       *
       * @return <code>true</code> when the string matches against the pattern,
       *         <code>false</code> otherwise.
       */
      public static boolean match(String pattern, String str) {
          return match(pattern, str, true);
      }
  
  
      /**
       * Matches a string against a pattern. The pattern contains two special
       * characters:
       * '*' which means zero or more characters,
       * '?' which means one and only one character.
       *
       * @param pattern the (non-null) pattern to match against
       * @param str     the (non-null) string that must be matched against the
       *                pattern
       *
       * @return <code>true</code> when the string matches against the pattern,
       *         <code>false</code> otherwise.
       */
      protected static boolean match(String pattern, String str, boolean isCaseSensitive) {
          char[] patArr = pattern.toCharArray();
          char[] strArr = str.toCharArray();
          int patIdxStart = 0;
          int patIdxEnd   = patArr.length-1;
          int strIdxStart = 0;
          int strIdxEnd   = strArr.length-1;
          char ch;
  
          boolean containsStar = false;
          for (int i = 0; i < patArr.length; i++) {
              if (patArr[i] == '*') {
                  containsStar = true;
                  break;
              }
          }
  
          if (!containsStar) {
              // No '*'s, so we make a shortcut
              if (patIdxEnd != strIdxEnd) {
                  return false; // Pattern and string do not have the same size
              }
              for (int i = 0; i <= patIdxEnd; i++) {
                  ch = patArr[i];
                  if (ch != '?') {
                      if (isCaseSensitive && ch != strArr[i]) {
                          return false;// Character mismatch
                      }
                      if (!isCaseSensitive && Character.toUpperCase(ch) !=
                          Character.toUpperCase(strArr[i])) {
                          return false; // Character mismatch
                      }
                  }
              }
              return true; // String matches against pattern
          }
  
          if (patIdxEnd == 0) {
              return true; // Pattern contains only '*', which matches anything
          }
  
          // Process characters before first star
          while((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
              if (ch != '?') {
                  if (isCaseSensitive && ch != strArr[strIdxStart]) {
                      return false;// Character mismatch
                  }
                  if (!isCaseSensitive && Character.toUpperCase(ch) !=
                      Character.toUpperCase(strArr[strIdxStart])) {
                      return false;// Character mismatch
                  }
              }
              patIdxStart++;
              strIdxStart++;
          }
          if (strIdxStart > strIdxEnd) {
              // All characters in the string are used. Check if only '*'s are
              // left in the pattern. If so, we succeeded. Otherwise failure.
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (patArr[i] != '*') {
                      return false;
                  }
              }
              return true;
          }
  
          // Process characters after last star
          while((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
              if (ch != '?') {
                  if (isCaseSensitive && ch != strArr[strIdxEnd]) {
                      return false;// Character mismatch
                  }
                  if (!isCaseSensitive && Character.toUpperCase(ch) !=
                      Character.toUpperCase(strArr[strIdxEnd])) {
                      return false;// Character mismatch
                  }
              }
              patIdxEnd--;
              strIdxEnd--;
          }
          if (strIdxStart > strIdxEnd) {
              // All characters in the string are used. Check if only '*'s are
              // left in the pattern. If so, we succeeded. Otherwise failure.
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (patArr[i] != '*') {
                      return false;
                  }
              }
              return true;
          }
  
          // process pattern between stars. padIdxStart and patIdxEnd point
          // always to a '*'.
          while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
              int patIdxTmp = -1;
              for (int i = patIdxStart+1; i <= patIdxEnd; i++) {
                  if (patArr[i] == '*') {
                      patIdxTmp = i;
                      break;
                  }
              }
              if (patIdxTmp == patIdxStart+1) {
                  // Two stars next to each other, skip the first one.
                  patIdxStart++;
                  continue;
              }
              // Find the pattern between padIdxStart & padIdxTmp in str between
              // strIdxStart & strIdxEnd
              int patLength = (patIdxTmp-patIdxStart-1);
              int strLength = (strIdxEnd-strIdxStart+1);
              int foundIdx  = -1;
              strLoop:
              for (int i = 0; i <= strLength - patLength; i++) {
                  for (int j = 0; j < patLength; j++) {
                      ch = patArr[patIdxStart+j+1];
                      if (ch != '?') {
                          if (isCaseSensitive && ch != strArr[strIdxStart+i+j]) {
                              continue strLoop;
                          }
                          if (!isCaseSensitive && Character.toUpperCase(ch) !=
                              Character.toUpperCase(strArr[strIdxStart+i+j])) {
                              continue strLoop;
                          }
                      }
                  }
  
                  foundIdx = strIdxStart+i;
                  break;
              }
  
              if (foundIdx == -1) {
                  return false;
              }
  
              patIdxStart = patIdxTmp;
              strIdxStart = foundIdx+patLength;
          }
  
          // All characters in the string are used. Check if only '*'s are left
          // in the pattern. If so, we succeeded. Otherwise failure.
          for (int i = patIdxStart; i <= patIdxEnd; i++) {
              if (patArr[i] != '*') {
                  return false;
              }
          }
          return true;
      }
  
  
  
      /**
       * Sets the basedir for scanning. This is the directory that is scanned
       * recursively. All '/' and '\' characters are replaced by
       * <code>File.separatorChar</code>. So the separator used need not match
       * <code>File.separatorChar</code>.
       *
       * @param basedir the (non-null) basedir for scanning
       */
      public void setBasedir(String basedir) {
          setBasedir(new File(basedir.replace('/',File.separatorChar).replace('\\',File.separatorChar)));
      }
  
  
  
      /**
       * Sets the basedir for scanning. This is the directory that is scanned
       * recursively.
       *
       * @param basedir the basedir for scanning
       */
      public void setBasedir(File basedir) {
          this.basedir = basedir;
      }
  
  
  
      /**
       * Gets the basedir that is used for scanning. This is the directory that
       * is scanned recursively.
       *
       * @return the basedir that is used for scanning
       */
      public File getBasedir() {
          return basedir;
      }
  
  
  
      /**
       * Sets the case sensitivity of the file system
       *
       * @param specifies if the filesystem is case sensitive
       */
      public void setCaseSensitive(boolean isCaseSensitive) {
          this.isCaseSensitive = isCaseSensitive;
      }
  
      /**
       * Sets the set of include patterns to use. All '/' and '\' characters are
       * replaced by <code>File.separatorChar</code>. So the separator used need
       * not match <code>File.separatorChar</code>.
       * <p>
       * When a pattern ends with a '/' or '\', "**" is appended.
       *
       * @param includes list of include patterns
       */
      public void setIncludes(String[] includes) {
          if (includes == null) {
              this.includes = null;
          } else {
              Pattern[] p = new Pattern[includes.length];
              for (int i = 0; i < includes.length; i++) {
                  p[i] = new Pattern();
                  p[i].setPattern(includes[i]);
              }
              setIncludes(p);
          }
      }
  
      public void setIncludes(Pattern[] includes) {
          if (includes == null) {
              this.includes = null;
          } else {
              this.includes = new Pattern[includes.length];
              for (int i = 0; i < includes.length; i++) {
                  String pattern;
                  pattern = includes[i].getPattern().replace('/',File.separatorChar).replace('\\',File.separatorChar);
                  if (pattern.endsWith(File.separator)) {
                      pattern += "**";
                  }
                  this.includes[i] = new Pattern();
                  this.includes[i].setPattern(pattern);
                  this.includes[i].setSelectorList(includes[i].getSelectorList());
              }
          }
      }
  
      /**
       * Sets the set of exclude patterns to use. All '/' and '\' characters are
       * replaced by <code>File.separatorChar</code>. So the separator used need
       * not match <code>File.separatorChar</code>.
       * <p>
       * When a pattern ends with a '/' or '\', "**" is appended.
       *
       * @param excludes list of exclude patterns
       */
      public void setExcludes(String[] excludes) {
          if (excludes == null) {
              this.excludes = null;
          } else {
              Pattern[] p = new Pattern[excludes.length];
              for (int i = 0; i < excludes.length; i++) {
                  p[i] = new Pattern();
                  p[i].setPattern(excludes[i]);
              }
              setExcludes(p);
          }
      }
  
      public void setExcludes(Pattern[] excludes) {
          if (excludes == null) {
              this.excludes = null;
          } else {
              this.excludes = new Pattern[excludes.length];
              for (int i = 0; i < excludes.length; i++) {
                  String pattern;
                  pattern = excludes[i].getPattern().replace('/',File.separatorChar).replace('\\',File.separatorChar);
                  if (pattern.endsWith(File.separator)) {
                      pattern += "**";
                  }
                  this.excludes[i] = new Pattern();
                  this.excludes[i].setPattern(pattern);
                  this.excludes[i].setSelectorList(excludes[i].getSelectorList());
              }
          }
      }
  
      /**
       * Has the scanner excluded or omitted any files or directories it
       * came accross?
       *
       * @return true if all files and directories that have been found,
       * are included.
       */
      public boolean isEverythingIncluded() {
          return everythingIncluded;
      }
  
  
      /**
       * Scans the base directory for files that match at least one include
       * pattern, and don't match any exclude patterns.
       *
       * @exception IllegalStateException when basedir was set incorrecly
       */
      public void scan() {
          if (basedir == null) {
              throw new IllegalStateException("No basedir set");
          }
          if (!basedir.exists()) {
              throw new IllegalStateException("basedir " + basedir
                                              + " does not exist");
          }
          if (!basedir.isDirectory()) {
              throw new IllegalStateException("basedir " + basedir
                                              + " is not a directory");
          }
  
          if (includes == null) {
              // No includes supplied, so set it to 'matches all'
              includes = new Pattern[1];
              includes[0] = new Pattern();
              includes[0].setPattern("**");
          }
          if (excludes == null) {
              excludes = new Pattern[0];
          }
  
          filesIncluded    = new Vector();
          filesNotIncluded = new Vector();
          filesExcluded    = new Vector();
          dirsIncluded     = new Vector();
          dirsNotIncluded  = new Vector();
          dirsExcluded     = new Vector();
  
          if (isIncluded("")) {
              if (!isExcluded("")) {
                  dirsIncluded.addElement("");
              } else {
                  dirsExcluded.addElement("");
              }
          } else {
              dirsNotIncluded.addElement("");
          }
          scandir(basedir, "", true);
      }
  
      /**
       * Toplevel invocation for the scan.
       *
       * <p>Returns immediately if a slow scan has already been requested.
       */
      protected void slowScan() {
          if (haveSlowResults) {
              return;
          }
  
          String[] excl = new String[dirsExcluded.size()];
          dirsExcluded.copyInto(excl);
  
          String[] notIncl = new String[dirsNotIncluded.size()];
          dirsNotIncluded.copyInto(notIncl);
  
          for (int i=0; i<excl.length; i++) {
              if (!couldHoldIncluded(excl[i])) {
                  scandir(new File(basedir, excl[i]),
                          excl[i]+File.separator, false);
              }
          }
  
          for (int i=0; i<notIncl.length; i++) {
              if (!couldHoldIncluded(notIncl[i])) {
                  scandir(new File(basedir, notIncl[i]),
                          notIncl[i]+File.separator, false);
              }
          }
  
          haveSlowResults  = true;
      }
  
  
      /**
       * Scans the passed dir for files and directories. Found files and
       * directories are placed in their respective collections, based on the
       * matching of includes and excludes. When a directory is found, it is
       * scanned recursively.
       *
       * @param dir   the directory to scan
       * @param vpath the path relative to the basedir (needed to prevent
       *              problems with an absolute path when using dir)
       *
       * @see #filesIncluded
       * @see #filesNotIncluded
       * @see #filesExcluded
       * @see #dirsIncluded
       * @see #dirsNotIncluded
       * @see #dirsExcluded
       */
      protected void scandir(File dir, String vpath, boolean fast) {
          String[] newfiles = dir.list();
  
          if (newfiles == null) {
              /*
               * two reasons are mentioned in the API docs for File.list
               * (1) dir is not a directory. This is impossible as
               *     we wouldn't get here in this case.
               * (2) an IO error occurred (why doesn't it throw an exception
               *     then???)
               */
              throw new BuildException("IO error scanning directory "
                                       + dir.getAbsolutePath());
          }
  
          for (int i = 0; i < newfiles.length; i++) {
              String name = vpath+newfiles[i];
              File   file = new File(dir,newfiles[i]);
              if (file.isDirectory()) {
                  if (isIncluded(name)) {
                      if (!isExcluded(name)) {
                          dirsIncluded.addElement(name);
                          if (fast) {
                              scandir(file, name+File.separator, fast);
                          }
                      } else {
                          everythingIncluded = false;
                          dirsExcluded.addElement(name);
                          if (fast && couldHoldIncluded(name)) {
                              scandir(file, name+File.separator, fast);
                          }
                      }
                  } else {
                      everythingIncluded = false;
                      dirsNotIncluded.addElement(name);
                      if (fast && couldHoldIncluded(name)) {
                          scandir(file, name+File.separator, fast);
                      }
                  }
                  if (!fast) {
                      scandir(file, name+File.separator, fast);
                  }
              } else if (file.isFile()) {
                  if (isIncluded(name)) {
                      if (!isExcluded(name)) {
                          filesIncluded.addElement(name);
                      } else {
                          everythingIncluded = false;
                          filesExcluded.addElement(name);
                      }
                  } else {
                      everythingIncluded = false;
                      filesNotIncluded.addElement(name);
                  }
              }
          }
      }
  
  
  
      /**
       * Tests whether a name matches against at least one include pattern.
       *
       * @param name the name to match
       * @return <code>true</code> when the name matches against at least one
       *         include pattern, <code>false</code> otherwise.
       */
      protected boolean isIncluded(String name) {
          for (int i = 0; i < includes.length; i++) {
              if (matchPath(includes[i].getPattern(),
                            includes[i].getSelectorList(),
                            name, isCaseSensitive)) {
                  return true;
              }
          }
          return false;
      }
  
      /**
       * Tests whether a name matches the start of at least one include pattern.
       *
       * @param name the name to match
       * @return <code>true</code> when the name matches against at least one
       *         include pattern, <code>false</code> otherwise.
       */
      protected boolean couldHoldIncluded(String name) {
          for (int i = 0; i < includes.length; i++) {
              if (matchPatternStart(includes[i].getPattern(),name, isCaseSensitive)) {
                  return true;
              }
          }
          return false;
      }
  
      /**
       * Tests whether a name matches against at least one exclude pattern.
       *
       * @param name the name to match
       * @return <code>true</code> when the name matches against at least one
       *         exclude pattern, <code>false</code> otherwise.
       */
      protected boolean isExcluded(String name) {
          for (int i = 0; i < excludes.length; i++) {
              if (matchPath(excludes[i].getPattern(),
                            excludes[i].getSelectorList(),
                            name, isCaseSensitive)) {
                  return true;
              }
          }
          return false;
      }
  
  
      /**
       * Get the names of the files that matched at least one of the include
       * patterns, and matched none of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the files
       */
      public String[] getIncludedFiles() {
          int count = filesIncluded.size();
          String[] files = new String[count];
          for (int i = 0; i < count; i++) {
              files[i] = (String)filesIncluded.elementAt(i);
          }
          return files;
      }
  
  
  
      /**
       * Get the names of the files that matched at none of the include patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the files
       */
      public String[] getNotIncludedFiles() {
          slowScan();
          int count = filesNotIncluded.size();
          String[] files = new String[count];
          for (int i = 0; i < count; i++) {
              files[i] = (String)filesNotIncluded.elementAt(i);
          }
          return files;
      }
  
  
  
      /**
       * Get the names of the files that matched at least one of the include
       * patterns, an matched also at least one of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the files
       */
      public String[] getExcludedFiles() {
          slowScan();
          int count = filesExcluded.size();
          String[] files = new String[count];
          for (int i = 0; i < count; i++) {
              files[i] = (String)filesExcluded.elementAt(i);
          }
          return files;
      }
  
  
  
      /**
       * Get the names of the directories that matched at least one of the include
       * patterns, an matched none of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the directories
       */
      public String[] getIncludedDirectories() {
          int count = dirsIncluded.size();
          String[] directories = new String[count];
          for (int i = 0; i < count; i++) {
              directories[i] = (String)dirsIncluded.elementAt(i);
          }
          return directories;
      }
  
  
  
      /**
       * Get the names of the directories that matched at none of the include
       * patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the directories
       */
      public String[] getNotIncludedDirectories() {
          slowScan();
          int count = dirsNotIncluded.size();
          String[] directories = new String[count];
          for (int i = 0; i < count; i++) {
              directories[i] = (String)dirsNotIncluded.elementAt(i);
          }
          return directories;
      }
  
  
  
      /**
       * Get the names of the directories that matched at least one of the include
       * patterns, an matched also at least one of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the directories
       */
      public String[] getExcludedDirectories() {
          slowScan();
          int count = dirsExcluded.size();
          String[] directories = new String[count];
          for (int i = 0; i < count; i++) {
              directories[i] = (String)dirsExcluded.elementAt(i);
          }
          return directories;
      }
  
  
  
      /**
       * Adds the array with default exclusions to the current exclusions set.
       *
       */
      public void addDefaultExcludes() {
          int excludesLength = excludes == null ? 0 : excludes.length;
          Pattern[] newExcludes;
          newExcludes = new Pattern[excludesLength + DEFAULTEXCLUDES.length];
          if (excludesLength > 0) {
              System.arraycopy(excludes,0,newExcludes,0,excludesLength);
          }
          for (int i = 0; i < DEFAULTEXCLUDES.length; i++) {
              newExcludes[i+excludesLength] = new Pattern();
              newExcludes[i+excludesLength].setPattern(DEFAULTEXCLUDES[i].replace('/',File.separatorChar).replace('\\',File.separatorChar));
          }
  
          Pattern[] ep = new Pattern[newExcludes.length];
          for (int i = 0; i < ep.length; i++) {
              ep[i] = new Pattern();
              ep[i].setPattern(newExcludes[i].getPattern());
          }
  
          excludes = ep;
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/FileScanner.java
  
  Index: FileScanner.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-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 "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
   * <http://www.apache.org/>.
   */
  package org.apache.tools.ant;
  
  import java.io.File;
  import org.apache.tools.ant.types.Pattern;
  
  /**
   * An interface used to describe the actions required by any type of
   * directory scanner.
   */
  public interface FileScanner {
      /**
       * Adds an array with default exclusions to the current exclusions set.
       *
       */
      void addDefaultExcludes();
      /**
       * Gets the basedir that is used for scanning. This is the directory that
       * is scanned recursively.
       *
       * @return the basedir that is used for scanning
       */
      File getBasedir();
      /**
       * Get the names of the directories that matched at least one of the include
       * patterns, an matched also at least one of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the directories
       */
      String[] getExcludedDirectories();
      /**
       * Get the names of the files that matched at least one of the include
       * patterns, an matched also at least one of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the files
       */
      String[] getExcludedFiles();
      /**
       * Get the names of the directories that matched at least one of the include
       * patterns, an matched none of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the directories
       */
      String[] getIncludedDirectories();
      /**
       * Get the names of the files that matched at least one of the include
       * patterns, an matched none of the exclude patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the files
       */
      String[] getIncludedFiles();
      /**
       * Get the names of the directories that matched at none of the include
       * patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the directories
       */
      String[] getNotIncludedDirectories();
      /**
       * Get the names of the files that matched at none of the include patterns.
       * The names are relative to the basedir.
       *
       * @return the names of the files
       */
      String[] getNotIncludedFiles();
      /**
       * Scans the base directory for files that match at least one include
       * pattern, and don't match any exclude patterns.
       *
       * @exception IllegalStateException when basedir was set incorrecly
       */
      void scan();
      /**
       * Sets the basedir for scanning. This is the directory that is scanned
       * recursively.
       *
       * @param basedir the (non-null) basedir for scanning
       */
      void setBasedir(String basedir);
      /**
       * Sets the basedir for scanning. This is the directory that is scanned
       * recursively.
       *
       * @param basedir the basedir for scanning
       */
      void setBasedir(File basedir);
      /**
       * Sets the set of exclude patterns to use.
       *
       * @param excludes list of exclude patterns
       */
      void setExcludes(String[] excludes);
      /**
       * Sets the set of include patterns to use.
       *
       * @param includes list of include patterns
       */
      void setIncludes(String[] includes);
      /**
       * Sets the set of exclude patterns to use.
       *
       * @param excludes list of exclude patterns
       */
      void setExcludes(Pattern[] excludes);
      /**
       * Sets the set of include patterns to use.
       *
       * @param includes list of include patterns
       */
      void setIncludes(Pattern[] includes);
  
      /**
       * Sets the case sensitivity of the file system
       *
       * @param specifies if the filesystem is case sensitive
       */
      void setCaseSensitive(boolean isCaseSensitive);
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/selectors/FileSelector.java
  
  Index: FileSelector.java
  ===================================================================
  /*
   * 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 "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
   * <http://www.apache.org/>.
   */
  package org.apache.tools.ant.selectors;
  
  import java.io.File;
  
  /**
   * File Selector API.
   *
   * @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
   */
  public interface FileSelector {
      public void setValue(final String value);
      public void setOperation(final String operation);
      public boolean isSelected(final String file);
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/selectors/FileTypeSelector.java
  
  Index: FileTypeSelector.java
  ===================================================================
  /*
   * 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 "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
   * <http://www.apache.org/>.
   */
   package org.apache.tools.ant.selectors;
  
  import java.io.File;
  
  /**
   * File selector that performs selection based on
   * file type - file and directory.
   *
   * @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
   */
  public class FileTypeSelector implements FileSelector {
      private String value = null;
      private String operation = "equals";
      private boolean cached = false;
      private boolean negate = false;
      private boolean checkForFile = false;
      private boolean checkForDir = false;
  
      public void setCached(final boolean cached) {
          this.cached = cached;
      }
  
      public boolean isCached() {
          return cached;
      }
  
      public void setValue(final String value) {
          this.value = value;
          setCached(false);
      }
  
      public void setOperation(final String operation) {
          this.operation = operation;
          setCached(false);
      }
  
      public void doCache() {
          if (!isCached()) {
              if (value == null) {
                  throw new NullPointerException("value must not be null.");
              }
              if (value.equalsIgnoreCase("file")) {
                  checkForFile = true;
                  checkForDir = false;
              } else if (value.equalsIgnoreCase("directory")) {
                  checkForDir = true;
                  checkForFile = false;
              }
              if (!operation.equalsIgnoreCase("equals")) {
                  negate = true;
              } else {
                  negate = false;
              }
              setCached(true);
          }
      }
  
      public boolean isSelected(final String file) {
          doCache();
          if (file == null) {
              throw new NullPointerException("file must not be null.");
          }
          boolean retValue = false;
          File f = new File(file);
          if (checkForFile) {
              retValue = f.isFile();
          } else if (checkForDir) {
              retValue = f.isDirectory();
          }
          if (negate) {
              retValue = !retValue;
          }
          return retValue;
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/selectors/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  type=org.apache.tools.ant.selectors.FileTypeSelector
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/types/FileSet.java
  
  Index: FileSet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-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 "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
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.FileScanner;
  import org.apache.tools.ant.DirectoryScanner;
  import org.apache.tools.ant.Project;
  
  import java.io.File;
  import java.util.Stack;
  import java.util.Vector;
  
  /**
   * Moved out of MatchingTask to make it a standalone object that could
   * be referenced (by scripts for example).
   *
   * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
   * @author Stefano Mazzocchi <a href="mailto:stefano@apache.org">stefano@apache.org</a>
   * @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a>
   * @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a>
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a>
   */
  public class FileSet extends DataType implements Cloneable {
  
      private PatternSet defaultPatterns = new PatternSet();
      private Vector additionalPatterns = new Vector();
  
      private File dir;
      private boolean useDefaultExcludes = true;
      private boolean isCaseSensitive = true;
  
      public FileSet() {
          super();
      }
  
      protected FileSet(FileSet fileset) {
          this.dir = fileset.dir;
          this.defaultPatterns = fileset.defaultPatterns;
          this.additionalPatterns = fileset.additionalPatterns;
          this.useDefaultExcludes = fileset.useDefaultExcludes;
          this.isCaseSensitive = fileset.isCaseSensitive;
          setProject(getProject());
      }
  
  
  
      /**
       * Makes this instance in effect a reference to another PatternSet
       * instance.
       *
       * <p>You must not set another attribute or nest elements inside
       * this element if you make it a reference.</p>
       */
      public void setRefid(Reference r) throws BuildException {
          if (dir != null || defaultPatterns.hasPatterns()) {
              throw tooManyAttributes();
          }
          if (!additionalPatterns.isEmpty()) {
              throw noChildrenAllowed();
          }
          super.setRefid(r);
      }
  
      public void setDir(File dir) throws BuildException {
          if (isReference()) {
              throw tooManyAttributes();
          }
  
          this.dir = dir;
      }
  
      public File getDir(Project p) {
          if (isReference()) {
              return getRef(p).getDir(p);
          }
          return dir;
      }
  
      public PatternSet createPatternSet() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          PatternSet patterns = new PatternSet();
          additionalPatterns.addElement(patterns);
          return patterns;
      }
  
      /**
       * add a name entry on the include list
       */
      public PatternSet.NameEntry createInclude() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return defaultPatterns.createInclude();
      }
  
      /**
       * add a name entry on the include files list
       */
      public PatternSet.NameEntry createIncludesFile() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return defaultPatterns.createIncludesFile();
      }
  
      /**
       * add a name entry on the exclude list
       */
      public PatternSet.NameEntry createExclude() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return defaultPatterns.createExclude();
      }
  
      /**
       * add a name entry on the include files list
       */
      public PatternSet.NameEntry createExcludesFile() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return defaultPatterns.createExcludesFile();
      }
  
      /**
       * Sets the set of include patterns. Patterns may be separated by a comma
       * or a space.
       *
       * @param includes the string containing the include patterns
       */
      public void setIncludes(String includes) {
          if (isReference()) {
              throw tooManyAttributes();
          }
  
          defaultPatterns.setIncludes(includes);
      }
  
      /**
       * Sets the set of exclude patterns. Patterns may be separated by a comma
       * or a space.
       *
       * @param excludes the string containing the exclude patterns
       */
      public void setExcludes(String excludes) {
          if (isReference()) {
              throw tooManyAttributes();
          }
  
          defaultPatterns.setExcludes(excludes);
      }
  
      /**
       * Sets the name of the file containing the includes patterns.
       *
       * @param incl The file to fetch the include patterns from.
       */
       public void setIncludesfile(File incl) throws BuildException {
           if (isReference()) {
               throw tooManyAttributes();
           }
  
           defaultPatterns.setIncludesfile(incl);
       }
  
      /**
       * Sets the name of the file containing the includes patterns.
       *
       * @param excl The file to fetch the exclude patterns from.
       */
       public void setExcludesfile(File excl) throws BuildException {
           if (isReference()) {
               throw tooManyAttributes();
           }
  
           defaultPatterns.setExcludesfile(excl);
       }
  
      /**
       * Sets whether default exclusions should be used or not.
       *
       * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
       *                           should be used, "false"|"off"|"no" when they
       *                           shouldn't be used.
       */
      public void setDefaultexcludes(boolean useDefaultExcludes) {
          if (isReference()) {
              throw tooManyAttributes();
          }
  
          this.useDefaultExcludes = useDefaultExcludes;
      }
  
      /**
       * Sets case sensitivity of the file system
       *
       * @param isCaseSensitive "true"|"on"|"yes" if file system is case
       *                           sensitive, "false"|"off"|"no" when not.
       */
      public void setCaseSensitive(boolean isCaseSensitive) {
          this.isCaseSensitive = isCaseSensitive;
      }
  
      /**
       * Returns the directory scanner needed to access the files to process.
       */
      public DirectoryScanner getDirectoryScanner(Project p) {
          if (isReference()) {
              return getRef(p).getDirectoryScanner(p);
          }
  
          if (dir == null) {
              throw new BuildException("No directory specified for fileset.");
          }
  
          if (!dir.exists()) {
              throw new BuildException(dir.getAbsolutePath()+" not found.");
          }
          if (!dir.isDirectory()) {
              throw new BuildException(dir.getAbsolutePath()+" is not a directory.");
          }
  
          DirectoryScanner ds = new DirectoryScanner();
          setupDirectoryScanner(ds, p);
          ds.scan();
          return ds;
      }
  
      public void setupDirectoryScanner(FileScanner ds, Project p) {
          if (ds == null) {
              throw new IllegalArgumentException("ds cannot be null");
          }
  
          ds.setBasedir(dir);
  
          for (int i=0; i<additionalPatterns.size(); i++) {
              Object o = additionalPatterns.elementAt(i);
              defaultPatterns.append2((PatternSet) o, p);
          }
  
          p.log( "FileSet: Setup file scanner in dir " + dir +
              " with " + defaultPatterns, p.MSG_DEBUG );
  
          ds.setIncludes(defaultPatterns.getIncludePatterns2(p));
          ds.setExcludes(defaultPatterns.getExcludePatterns2(p));
          if (useDefaultExcludes) {
            ds.addDefaultExcludes();
          }
          ds.setCaseSensitive(isCaseSensitive);
      }
  
      /**
       * Performs the check for circular references and returns the
       * referenced FileSet.
       */
      protected FileSet getRef(Project p) {
          if (!checked) {
              Stack stk = new Stack();
              stk.push(this);
              dieOnCircularReference(stk, p);
          }
  
          Object o = ref.getReferencedObject(p);
          if (!(o instanceof FileSet)) {
              String msg = ref.getRefId()+" doesn\'t denote a fileset";
              throw new BuildException(msg);
          } else {
              return (FileSet) o;
          }
      }
  
      /**
       * Return a FileSet that has the same basedir and same patternsets
       * as this one.
       */
      public Object clone() {
          if (isReference()) {
              return new FileSet(getRef(getProject()));
          } else {
              return new FileSet(this);
          }
      }
  
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/types/Pattern.java
  
  Index: Pattern.java
  ===================================================================
  /*
   * 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 "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
   * <http://www.apache.org/>.
   */
   package org.apache.tools.ant.types;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.ProjectHelper;
  import org.apache.tools.ant.BuildException;
  
  import java.io.*;
  import java.util.Enumeration;
  import java.util.Stack;
  import java.util.StringTokenizer;
  import java.util.Vector;
  
  /**
   * Named collection of include/exclude tags.
   *
   * @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
   */
  public class Pattern {
      private String pattern = null;
      private Vector selectorList = null;
  
      /**
       * Set the pattern
       * @param pattern    the pattern to match
       */
      public void setPattern(String pattern) {
          this.pattern = pattern;
      }
  
      /**
       * Set the list of Selector entries
       * @param selectorList    the vector list of 'SelectorEntry's
       */
      public void setSelectorList(Vector selectorList) {
          this.selectorList = selectorList;
      }
  
      /**
       * Get the pattern
       */
      public String getPattern() {
          return pattern;
      }
  
      /**
       * Get the list of Selector entries
       */
      public Vector getSelectorList() {
          return selectorList;
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/types/PatternSet.java
  
  Index: PatternSet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-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 "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
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.ProjectHelper;
  import org.apache.tools.ant.BuildException;
  
  import java.io.File;
  import java.io.BufferedReader;
  import java.io.FileReader;
  import java.io.IOException;
  import java.util.Enumeration;
  import java.util.Stack;
  import java.util.StringTokenizer;
  import java.util.Vector;
  
  /**
   * Named collection of include/exclude tags.
   *
   * <p>Moved out of MatchingTask to make it a standalone object that
   * could be referenced (by scripts for example).
   *
   * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
   * @author Stefano Mazzocchi <a href="mailto:stefano@apache.org">stefano@apache.org</a>
   * @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a>
   * @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a>
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   * @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
   */
  public class PatternSet extends DataType {
      private Vector includeList = new Vector();
      private Vector excludeList = new Vector();
      private Vector includesFileList = new Vector();
      private Vector excludesFileList = new Vector();
  
  
       /**
       * inner class to hold a selector list.  A SelectorEntry
       * is made up of the pattern and selection detail.
       */
      public static class SelectorEntry {
          private String type;
          private String value;
          private String operation;
  
          public void setType(String t) {
              this.type = t;
          }
  
          public void setValue(String val) {
              this.value = val;
          }
  
          public void setOperation(String op) {
              this.operation = op;
          }
  
          public String getType() {
              return type;
          }
  
          public String getValue() {
              return value;
          }
  
          public String getOperation() {
              return operation;
          }
      }
  
      /**
       * inner class to hold a name on list.  "If" and "Unless" attributes
       * may be used to invalidate the entry based on the existence of a
       * property (typically set thru the use of the Available task).
       */
      public class NameEntry {
          private String name;
          private String ifCond;
          private String unlessCond;
          private Vector selectorList = new Vector();
  
          public void setName(String name) {
              this.name = name;
          }
  
          public void setIf(String cond) {
              ifCond = cond;
          }
  
          public void setUnless(String cond) {
              unlessCond = cond;
          }
  
          /**
           * Include/Exclude can contain nested selectors
           */
          public SelectorEntry createSelector() {
              if (isReference()) {
                  throw noChildrenAllowed();
              }
              return addSelectorToList(selectorList);
          }
  
          /**
           * add a selector entry to the given list
           */
          private SelectorEntry addSelectorToList(final Vector list) {
              final SelectorEntry result = new SelectorEntry();
              list.addElement(result);
              return result;
          }
  
          public String getName() {
              return name;
          }
  
          public Vector getSelectorList() {
              return selectorList;
          }
  
          public String evalName(Project p) {
              return valid(p) ? name : null;
          }
  
          private boolean valid(Project p) {
              if (ifCond != null && p.getProperty(ifCond) == null) {
                  return false;
              } else if (unlessCond != null && p.getProperty(unlessCond) != null) {
                  return false;
              }
              return true;
          }
  
          public String toString() {
              StringBuffer buf = new StringBuffer(name);
              if ((ifCond != null) || (unlessCond != null)) {
                  buf.append(":");
                  String connector = "";
  
                  if (ifCond != null) {
                      buf.append("if->");
                      buf.append(ifCond);
                      connector = ";";
                  }
                  if (unlessCond != null) {
                      buf.append(connector);
                      buf.append("unless->");
                      buf.append(unlessCond);
                  }
              }
  
              return buf.toString();
          }
  
          public void setSelectorList(Vector list) {
              this.selectorList = list;
          }
      }
  
      public PatternSet() {
          super();
      }
  
      /**
       * Makes this instance in effect a reference to another PatternSet
       * instance.
       *
       * <p>You must not set another attribute or nest elements inside
       * this element if you make it a reference.</p>
       */
      public void setRefid(Reference r) throws BuildException {
          if (!includeList.isEmpty() || !excludeList.isEmpty()) {
              throw tooManyAttributes();
          }
          super.setRefid(r);
      }
  
      /**
       * add a name entry on the include list
       */
      public NameEntry createInclude() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return addPatternToList(includeList);
      }
  
      /**
       * add a name entry on the include files list
       */
      public NameEntry createIncludesFile() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return addPatternToList(includesFileList);
      }
  
      /**
       * add a name entry on the exclude list
       */
      public NameEntry createExclude() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return addPatternToList(excludeList);
      }
  
      /**
       * add a name entry on the exclude files list
       */
      public NameEntry createExcludesFile() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          return addPatternToList(excludesFileList);
      }
  
      /**
       * Sets the set of include patterns. Patterns may be separated by a comma
       * or a space.
       *
       * @param includes the string containing the include patterns
       */
      public void setIncludes(String includes) {
          if (isReference()) {
              throw tooManyAttributes();
          }
          if (includes != null && includes.length() > 0) {
              StringTokenizer tok = new StringTokenizer(includes, ", ", false);
              while (tok.hasMoreTokens()) {
                  createInclude().setName(tok.nextToken());
              }
          }
      }
  
      /**
       * Sets the set of exclude patterns. Patterns may be separated by a comma
       * or a space.
       *
       * @param excludes the string containing the exclude patterns
       */
      public void setExcludes(String excludes) {
          if (isReference()) {
              throw tooManyAttributes();
          }
          if (excludes != null && excludes.length() > 0) {
              StringTokenizer tok = new StringTokenizer(excludes, ", ", false);
              while (tok.hasMoreTokens()) {
                  createExclude().setName(tok.nextToken());
              }
          }
      }
  
      /**
       * add a name entry to the given list
       */
      private NameEntry addPatternToList(Vector list) {
          NameEntry result = new NameEntry();
          list.addElement(result);
          return result;
      }
  
      /**
       * Sets the name of the file containing the includes patterns.
       *
       * @param includesFile The file to fetch the include patterns from.
       */
       public void setIncludesfile(File includesFile) throws BuildException {
           if (isReference()) {
               throw tooManyAttributes();
           }
           createIncludesFile().setName(includesFile.getAbsolutePath());
       }
  
      /**
       * Sets the name of the file containing the excludes patterns.
       *
       * @param excludesFile The file to fetch the exclude patterns from.
       */
       public void setExcludesfile(File excludesFile) throws BuildException {
           if (isReference()) {
               throw tooManyAttributes();
           }
           createExcludesFile().setName(excludesFile.getAbsolutePath());
       }
  
      /**
       *  Reads path matching patterns from a file and adds them to the
       *  includes or excludes list (as appropriate).
       */
      private void readPatterns(File patternfile, Vector patternlist, Project p)
          throws BuildException {
  
          BufferedReader patternReader = null;
          try {
              // Get a FileReader
              patternReader =
                  new BufferedReader(new FileReader(patternfile));
  
              // Create one NameEntry in the appropriate pattern list for each
              // line in the file.
              String line = patternReader.readLine();
              while (line != null) {
                  if (line.length() > 0) {
                      line = p.replaceProperties(line);
                      addPatternToList(patternlist).setName(line);
                  }
                  line = patternReader.readLine();
              }
          } catch(IOException ioe)  {
              String msg = "An error occured while reading from pattern file: "
                  + patternfile;
              throw new BuildException(msg, ioe);
          } finally {
              if( null != patternReader ) {
                  try {
                      patternReader.close();
                  } catch(IOException ioe) {
                      //Ignore exception
                  }
              }
          }
      }
  
      public void append2(PatternSet other, Project p) {
           if (isReference()) {
               throw new BuildException("Cannot append to a reference");
           }
          Pattern[] incl = other.getIncludePatterns2(p);
          if (incl != null) {
              for (int i=0; i<incl.length; i++) {
                  NameEntry ne = createInclude();
                  ne.setName(incl[i].getPattern());
                  ne.setSelectorList(incl[i].getSelectorList());
              }
          }
  
          Pattern[] excl = other.getExcludePatterns2(p);
          if (excl != null) {
              for (int i=0; i<excl.length; i++) {
                  NameEntry ne = createExclude();
                  ne.setName(excl[i].getPattern());
                  ne.setSelectorList(incl[i].getSelectorList());
              }
          }
      }
  
      /**
       * Adds the patterns of the other instance to this set.
       */
      public void append(PatternSet other, Project p) {
          if (isReference()) {
              throw new BuildException("Cannot append to a reference");
          }
  
          String[] incl = other.getIncludePatterns(p);
          if (incl != null) {
              for (int i=0; i<incl.length; i++) {
                  createInclude().setName(incl[i]);
              }
          }
  
          String[] excl = other.getExcludePatterns(p);
          if (excl != null) {
              for (int i=0; i<excl.length; i++) {
                  createExclude().setName(excl[i]);
              }
          }
      }
  
      /**
       * Returns the filtered include patterns as an array of Patterns
       */
      public Pattern[] getIncludePatterns2(Project p) {
          if (isReference()) {
              return getRef(p).getIncludePatterns2(p);
          } else {
              readFiles(p);
              return makeArray2(includeList, p);
          }
      }
  
      /**
       * Returns the filtered exclude patterns as an array of Patterns
       */
      public Pattern[] getExcludePatterns2(Project p) {
          if (isReference()) {
              return getRef(p).getExcludePatterns2(p);
          } else {
              readFiles(p);
              return makeArray2(excludeList, p);
          }
      }
  
      /**
       * Returns the filtered include patterns.
       */
      public String[] getIncludePatterns(Project p) {
          if (isReference()) {
              return getRef(p).getIncludePatterns(p);
          } else {
              readFiles(p);
              return makeArray(includeList, p);
          }
      }
  
      /**
       * Returns the filtered include patterns.
       */
      public String[] getExcludePatterns(Project p) {
          if (isReference()) {
              return getRef(p).getExcludePatterns(p);
          } else {
              readFiles(p);
              return makeArray(excludeList, p);
          }
      }
  
      /**
       * helper for FileSet.
       */
      boolean hasPatterns() {
          return includesFileList.size() > 0 || excludesFileList.size() > 0
              || includeList.size() > 0 || excludeList.size() > 0;
      }
  
      /**
       * Performs the check for circular references and returns the
       * referenced PatternSet.
       */
      private PatternSet getRef(Project p) {
          if (!checked) {
              Stack stk = new Stack();
              stk.push(this);
              dieOnCircularReference(stk, p);
          }
  
          Object o = ref.getReferencedObject(p);
          if (!(o instanceof PatternSet)) {
              String msg = ref.getRefId()+" doesn\'t denote a patternset";
              throw new BuildException(msg);
          } else {
              return (PatternSet) o;
          }
      }
  
  
       /**
       * Convert a vector of NameEntry elements into an array of Patterns
       */
      private Pattern[] makeArray2(Vector list, Project p) {
          if (list.size() == 0) return null;
  
          Vector tmpPatterns = new Vector();
          for (Enumeration e = list.elements() ; e.hasMoreElements() ;) {
              NameEntry ne = (NameEntry)e.nextElement();
              String pattern = ne.evalName(p);
              if (pattern != null && pattern.length() > 0) {
                  Pattern pat = new Pattern();
                  pat.setPattern(pattern);
                  pat.setSelectorList(ne.getSelectorList());
                  tmpPatterns.addElement(pat);
              }
          }
  
          Pattern result[] = new Pattern[tmpPatterns.size()];
          tmpPatterns.copyInto(result);
          return result;
      }
  
      /**
       * Convert a vector of NameEntry elements into an array of Strings.
       */
      private String[] makeArray(Vector list, Project p) {
          if (list.size() == 0) {
            return null;
          }
  
          Vector tmpNames = new Vector();
          for (Enumeration e = list.elements() ; e.hasMoreElements() ;) {
              NameEntry ne = (NameEntry)e.nextElement();
              String pattern = ne.evalName(p);
              if (pattern != null && pattern.length() > 0) {
                  tmpNames.addElement(pattern);
              }
          }
  
          String result[] = new String[tmpNames.size()];
          tmpNames.copyInto(result);
          return result;
      }
  
      /**
       * Read includesfile ot excludesfile if not already done so.
       */
      private void readFiles(Project p) {
          if (includesFileList.size() > 0) {
              Enumeration e = includesFileList.elements();
              while (e.hasMoreElements()) {
                  NameEntry ne = (NameEntry)e.nextElement();
                  String fileName = ne.evalName(p);
                  if (fileName != null) {
                      File inclFile = p.resolveFile(fileName);
                      if (!inclFile.exists()) {
                          throw new BuildException("Includesfile "
                                                   + inclFile.getAbsolutePath()
                                                   + " not found.");
                      }
                      readPatterns(inclFile, includeList, p);
                  }
              }
              includesFileList.removeAllElements();
          }
  
          if (excludesFileList.size() > 0) {
              Enumeration e = excludesFileList.elements();
              while (e.hasMoreElements()) {
                  NameEntry ne = (NameEntry)e.nextElement();
                  String fileName = ne.evalName(p);
                  if (fileName != null) {
                      File exclFile = p.resolveFile(fileName);
                      if (!exclFile.exists()) {
                          throw new BuildException("Excludesfile "
                                                   + exclFile.getAbsolutePath()
                                                   + " not found.");
                      }
                      readPatterns(exclFile, excludeList, p);
                  }
              }
              excludesFileList.removeAllElements();
          }
      }
  
      public String toString()
      {
          return "patternSet{ includes: " + includeList +
              " excludes: " + excludeList + " }";
      }
  
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/selectors/src/main/org/apache/tools/ant/types/ZipScanner.java
  
  Index: ZipScanner.java
  ===================================================================
  /*
   * 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
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types;
  
  import org.apache.tools.ant.DirectoryScanner;
  import org.apache.tools.ant.types.Pattern;
  import java.io.File;
  
  /**
   * ZipScanner accesses the pattern matching algorithm in DirectoryScanner,
   * which are protected methods that can only be accessed by subclassing.
   *
   * This implementation of FileScanner defines getIncludedFiles to return
   * only the Zip File which is being scanned, not the matching Zip entries.
   * Arguably, it should return the matching entries, however this would
   * complicate existing code which assumes that FileScanners return a
   * set of file system files that can be accessed directly.
   *
   * @author Don Ferguson <a href="mailto:don@bea.com">don@bea.com</a>
   */
  public class ZipScanner extends DirectoryScanner {
  
      /**
       * The zip file which should be scanned.
       */
      protected File srcFile;
  
      /**
       * Sets the srcFile for scanning. This is the jar or zip file that is scanned
       * for matching entries.
       *
       * @param srcFile the (non-null) zip file name for scanning
       */
      public void setSrc(File srcFile) {
          this.srcFile = srcFile;
      }
  
      /**
       * Returns the zip file itself, not the matching entries within the zip file.
       * This keeps the uptodate test in the Zip task simple; otherwise we'd need
       * to treat zip filesets specially.
       *
       * @return the source file from which entries will be extracted.
       */
      public String[] getIncludedFiles() {
          String[] result = new String[1];
          result[0] = srcFile.getAbsolutePath();
          return result;
      }
  
      /**
       * Returns an empty list of directories to create.
       */
      public String[] getIncludedDirectories() {
          return new String[0];
      }
  
      /**
       * Initialize DirectoryScanner data structures.
       */
      public void init() {
          if (includes == null) {
              // No includes supplied, so set it to 'matches all'
              includes = new Pattern[1];
              includes[0] = new Pattern();
              includes[0].setPattern("**");
          }
          if (excludes == null) {
              excludes = new Pattern[0];
          }
      }
  
      /**
       * Matches a jar entry against the includes/excludes list,
       * normalizing the path separator.
       *
       * @param path the (non-null) path name to test for inclusion
       *
       * @return <code>true</code> if the path should be included
       *         <code>false</code> otherwise.
       */
      public boolean match(String path) {
          String vpath = path.replace('/', File.separatorChar).
              replace('\\', File.separatorChar);
          return isIncluded(vpath) && !isExcluded(vpath);
      }
  
  }
  
  
  

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


Mime
View raw message