diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
index 6ab4a8f..3cfe57f 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
@@ -26,16 +26,14 @@
 import com.google.gwt.dev.javac.JavaSourceOracle;
 import com.google.gwt.dev.javac.impl.JavaSourceOracleImpl;
 import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.resource.impl.DefaultFilters;
 import com.google.gwt.dev.resource.impl.PathPrefix;
 import com.google.gwt.dev.resource.impl.PathPrefixSet;
-import com.google.gwt.dev.resource.impl.ResourceFilter;
 import com.google.gwt.dev.resource.impl.ResourceOracleImpl;
 import com.google.gwt.dev.util.Empty;
 import com.google.gwt.dev.util.PerfLogger;
 import com.google.gwt.dev.util.Util;
 
-import org.apache.tools.ant.types.ZipScanner;
-
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -54,11 +52,6 @@
  * XML for unit tests.
  */
 public class ModuleDef implements PublicOracle {
-  /**
-   * Default to recursive inclusion of java files if no explicit include
-   * directives are specified.
-   */
-  private static final String[] DEFAULT_SOURCE_FILE_INCLUDES_LIST = new String[] {"**/*.java"};
 
   private static final Comparator<Map.Entry<String, ?>> REV_NAME_CMP = new Comparator<Map.Entry<String, ?>>() {
     public int compare(Map.Entry<String, ?> entry1, Map.Entry<String, ?> entry2) {
@@ -123,9 +116,11 @@
   private PathPrefixSet sourcePrefixSet = new PathPrefixSet();
 
   private final Styles styles = new Styles();
+  private final DefaultFilters defaultFilters;
 
   public ModuleDef(String name) {
     this.name = name;
+    defaultFilters = new DefaultFilters();
   }
 
   public synchronized void addEntryPointTypeName(String typeName) {
@@ -155,15 +150,9 @@
     if (lazyPublicOracle != null) {
       throw new IllegalStateException("Already normalized");
     }
-
-    final ZipScanner scanner = getScanner(includeList, excludeList,
-        defaultExcludes, caseSensitive);
-
-    publicPrefixSet.add(new PathPrefix(publicPackage, new ResourceFilter() {
-      public boolean allows(String path) {
-        return scanner.match(path);
-      }
-    }, true));
+    publicPrefixSet.add(new PathPrefix(publicPackage,
+        defaultFilters.customResourceFilter(includeList, excludeList,
+            defaultExcludes, caseSensitive), true));
   }
 
   public void addSourcePackage(String sourcePackage, String[] includeList,
@@ -178,25 +167,9 @@
     if (lazySourceOracle != null) {
       throw new IllegalStateException("Already normalized");
     }
-
-    if (includeList.length == 0) {
-      /*
-       * If no includes list was provided then, use the default.
-       */
-      includeList = DEFAULT_SOURCE_FILE_INCLUDES_LIST;
-    }
-
-    final ZipScanner scanner = getScanner(includeList, excludeList,
-        defaultExcludes, caseSensitive);
-
-    ResourceFilter sourceFileFilter = new ResourceFilter() {
-      public boolean allows(String path) {
-        return path.endsWith(".java") && scanner.match(path);
-      }
-    };
-
-    PathPrefix pathPrefix = new PathPrefix(sourcePackage, sourceFileFilter,
-        isSuperSource);
+    PathPrefix pathPrefix = new PathPrefix(sourcePackage,
+        defaultFilters.customJavaFilter(includeList, excludeList,
+            defaultExcludes, caseSensitive), isSuperSource);
     sourcePrefixSet.add(pathPrefix);
   }
 
@@ -468,27 +441,4 @@
     PerfLogger.end();
   }
 
-  private ZipScanner getScanner(String[] includeList, String[] excludeList,
-      boolean defaultExcludes, boolean caseSensitive) {
-    /*
-     * Hijack Ant's ZipScanner to handle inclusions/exclusions exactly as Ant
-     * does. We're only using its pattern-matching capabilities; the code path
-     * I'm using never tries to hit the filesystem in Ant 1.6.5.
-     */
-    ZipScanner scanner = new ZipScanner();
-    if (includeList.length > 0) {
-      scanner.setIncludes(includeList);
-    }
-    if (excludeList.length > 0) {
-      scanner.setExcludes(excludeList);
-    }
-    if (defaultExcludes) {
-      scanner.addDefaultExcludes();
-    }
-    scanner.setCaseSensitive(caseSensitive);
-    scanner.init();
-
-    return scanner;
-  }
-
 }
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java b/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java
new file mode 100644
index 0000000..3ff40d8
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.resource.impl;
+
+import org.apache.tools.ant.types.ZipScanner;
+
+import java.util.regex.Pattern;
+
+/**
+ * A singleton class that provides blazingly fast implementation of the default
+ * excludes of Ant's {@link org.apache.tools.ant.DirectoryScanner}, assuming
+ * case-sensitiveness.
+ * 
+ * TODO: this class needs to be revisited, when Gwt's Ant is upgraded.
+ * 
+ * Currently, we do not go to ant if (a) the filterList is empty, or (b) the
+ * filterList has "common" patterns. Exception: When pattern or path ends in
+ * '/', we defer to ant.
+ * 
+ * TODO: This code could be made more general and cleaner by removing the
+ * dependency on Ant completely. All ant patterns could be compiled into
+ * reg-exps. That could also make the code faster. Plus, at several places,
+ * Ant's documentation seems to be incomplete. Instead, perhaps, we should
+ * specify our own rules for writing patterns.
+ */
+public class DefaultFilters {
+
+  private static final boolean IS_EXCLUDES = false;
+  private static final boolean IS_INCLUDES = true;
+  private static final boolean NOT_JAVA = false;
+  private static final boolean YES_JAVA = true;
+
+  static ZipScanner getScanner(String[] includeList, String[] excludeList,
+      boolean defaultExcludes, boolean caseSensitive) {
+    /*
+     * Hijack Ant's ZipScanner to handle inclusions/exclusions exactly as Ant
+     * does. We're only using its pattern-matching capabilities; the code path
+     * I'm using never tries to hit the filesystem in Ant 1.6.5.
+     */
+    ZipScanner scanner = new ZipScanner();
+    if (includeList.length > 0) {
+      scanner.setIncludes(includeList);
+    }
+    if (excludeList.length > 0) {
+      scanner.setExcludes(excludeList);
+    }
+    if (defaultExcludes) {
+      scanner.addDefaultExcludes();
+    }
+    scanner.setCaseSensitive(caseSensitive);
+    scanner.init();
+
+    return scanner;
+  }
+
+  /* used when defaultExcludes is true */
+  final ResourceFilter defaultResourceFilter = new ResourceFilter() {
+
+    public boolean allows(String path) {
+      return defaultAntIncludes.allows(path)
+          && !defaultExcludesPattern.matcher(path).matches();
+    }
+  };
+
+  /* used when defaultExcludes is true */
+  final ResourceFilter defaultJavaFilter = new ResourceFilter() {
+
+    public boolean allows(String path) {
+      return justJavaFilter.allows(path)
+          && !defaultJavaExcludesPattern.matcher(path).matches();
+    }
+
+  };
+  /* used when defaultExcludes is false */
+  final ResourceFilter justResourceFilter = new ResourceFilter() {
+
+    public boolean allows(String path) {
+      return defaultAntIncludes.allows(path);
+    }
+  };
+
+  /* used when defaultExcludes is false */
+  final ResourceFilter justJavaFilter = new ResourceFilter() {
+
+    public boolean allows(String path) {
+      return defaultAntIncludes.allows(path) && isJavaFile(path);
+    }
+  };
+
+  private final Pattern defaultExcludesPattern;
+  private final Pattern defaultJavaExcludesPattern;
+  // \w (word character), ., $, /, -, *, ~, #, %
+  private final Pattern antPattern = Pattern.compile("^[\\w\\.\\$/\\-\\*~#%]*$");
+
+  // accepts all but paths starting with '/'. Default include list is '**'
+  private final ResourceFilter defaultAntIncludes = new ResourceFilter() {
+    public boolean allows(String path) {
+      return path.charAt(0) != '/';
+    }
+  };
+
+  private final ResourceFilter rejectAll = new ResourceFilter() {
+    public boolean allows(String path) {
+      return false;
+    }
+  };
+
+  public DefaultFilters() {
+
+    /*
+     * list copied from {@link org.apache.tools.ant.DirectoryScanner}
+     */
+    String defaultExcludes[] = new String[] {
+    // Miscellaneous typical temporary files
+        "**/*~", "**/#*#", "**/.#*", "**/%*%", "**/._*",
+
+        // CVS
+        "**/CVS", "**/CVS/**",
+        // to not hit the weird formatting error.
+        "**/.cvsignore",
+
+        // SCCS
+        "**/SCCS", "**/SCCS/**",
+
+        // Visual SourceSafe
+        "**/vssver.scc",
+
+        // Subversion
+        "**/.svn", "**/.svn/**",
+
+        // Mac
+        "**/.DS_Store",};
+
+    defaultExcludesPattern = getPatternFromAntStrings(defaultExcludes);
+
+    String defaultExcludesJava[] = new String[] {
+    // Miscellaneous typical temporary files
+        "**/.#*", "**/._*",
+
+        // CVS
+        "**/CVS/**",
+
+        // SCCS
+        "**/SCCS/**",
+
+        // Subversion
+        "**/.svn/**",};
+    defaultJavaExcludesPattern = getPatternFromAntStrings(defaultExcludesJava);
+  }
+
+  public ResourceFilter customJavaFilter(String includeList[],
+      String excludeList[], boolean defaultExcludes, boolean caseSensitive) {
+    return getCustomFilter(includeList, excludeList, defaultExcludes,
+        caseSensitive, YES_JAVA);
+  }
+
+  public ResourceFilter customResourceFilter(String includeList[],
+      String excludeList[], boolean defaultExcludes, boolean caseSensitive) {
+
+    return getCustomFilter(includeList, excludeList, defaultExcludes,
+        caseSensitive, NOT_JAVA);
+  }
+
+  /**
+   * return a customResourceFiter that handles all the argument. If unable to
+   * create a customResourceFilter that handles the arguments, catchAll is used
+   * as the final ResourceFilter.
+   */
+  ResourceFilter customFilterWithCatchAll(final String includeList[],
+      final String excludeList[], final boolean defaultExcludes,
+      final ResourceFilter catchAll, final boolean isJava) {
+
+    assert includeList.length > 0 || excludeList.length > 0;
+
+    final ResourceFilter includeFilter = getFilterPart(includeList, IS_INCLUDES);
+    final ResourceFilter excludeFilter = getFilterPart(excludeList, IS_EXCLUDES);
+
+    if (includeFilter == null || excludeFilter == null) {
+      return catchAll;
+    }
+    // another common-case
+    ResourceFilter filter = new ResourceFilter() {
+      public boolean allows(String path) {
+        // do not handle the case when pattern ends in '/'
+        if (path.endsWith("/")) {
+          return catchAll.allows(path);
+        }
+        return isPathAllowedByDefaults(path, defaultExcludes, isJava)
+            && includeFilter.allows(path) && !excludeFilter.allows(path);
+      }
+
+      private boolean isPathAllowedByDefaults(String path,
+          boolean defaultExcludes, boolean isJava) {
+        if (defaultExcludes) {
+          return isJava ? !defaultJavaExcludesPattern.matcher(path).matches()
+              && isJavaFile(path)
+              : !defaultExcludesPattern.matcher(path).matches();
+        }
+        return isJava ? isJavaFile(path) : true;
+      }
+    };
+    return filter;
+  }
+
+  ResourceFilter getCustomFilter(final String includeList[],
+      final String excludeList[], final boolean defaultExcludes,
+      final boolean caseSensitive, final boolean isJava) {
+    if (includeList.length == 0 && excludeList.length == 0 && caseSensitive) {
+      // optimize for the common case.
+      return getMatchingDefaultFilter(defaultExcludes, isJava);
+    }
+
+    // don't create a catchAll in default cases
+    ResourceFilter catchAll = new ResourceFilter() {
+      ZipScanner scanner = getScanner(includeList, excludeList,
+          defaultExcludes, caseSensitive);
+
+      public boolean allows(String path) {
+        if (isJava) {
+          return isJavaFile(path) && scanner.match(path);
+        }
+        return scanner.match(path);
+      }
+    };
+
+    // for now, don't handle case sensitivity
+    if (!caseSensitive) {
+      return catchAll;
+    }
+    return customFilterWithCatchAll(includeList, excludeList, defaultExcludes,
+        catchAll, isJava);
+  }
+
+  ResourceFilter getFilterPart(final String list[], final boolean defaultValue) {
+    if (list.length == 0) {
+      return defaultValue ? defaultAntIncludes : rejectAll;
+    }
+
+    String patternStrings[] = new String[list.length];
+    int count = 0;
+    for (String antPatternString : list) {
+      String patternString = getPatternFromAntPattern(antPatternString);
+      if (patternString == null) {
+        return null;
+      }
+      patternStrings[count++] = patternString;
+    }
+
+    final Pattern pattern = getPatternFromStrings(patternStrings);
+    return new ResourceFilter() {
+      public boolean allows(String path) {
+        return pattern.matcher(path).matches();
+      }
+    };
+  }
+
+  /**
+   * Returns a pattern string that can be passed in Java Pattern.compile(..).
+   * For spec, see <a href="http://www.jajakarta.org/ant/ant-1.6.1/docs/ja/manual/api/org/apache/tools/ant/DirectoryScanner.html"
+   * >DirectoryScanner</a> From the spec: There is a special case regarding the
+   * use of File.separators at the beginning of the pattern and the string to
+   * match: When a pattern starts with a File.separator, the string to match
+   * must also start with a File.separator. When a pattern does not start with a
+   * File.separator, the string to match may not start with a File.separator.
+   * 
+   * </p>
+   * 
+   * TODO: This method could accept all ant patterns, but then all characters
+   * that have a special meaning in Java's regular expression would need to be
+   * escaped.
+   * 
+   * @param antPatternString the ant pattern String.
+   * @return a pattern string that can be passed in Java's Pattern.compile(..),
+   *         null if cannot process the pattern.
+   */
+  String getPatternFromAntPattern(String antPatternString) {
+    if (!antPattern.matcher(antPatternString).matches()) {
+      return null;
+    }
+    // do not handle patterns that have ***
+    if (antPatternString.indexOf("***") != -1) {
+      return null;
+    }
+    StringBuffer sb = new StringBuffer();
+    int length = antPatternString.length();
+    for (int i = 0; i < length; i++) {
+      char c = antPatternString.charAt(i);
+      switch (c) {
+        case '.':
+          sb.append("\\.");
+          break;
+        case '$':
+          sb.append("\\$");
+          break;
+        case '/':
+          // convert /** to (/[^/]*)* except when / is the first char.
+          if (i != 0 && i + 2 < length && antPatternString.charAt(i + 1) == '*'
+              && antPatternString.charAt(i + 2) == '*') {
+            sb.append("(/[^/]*)*");
+            i += 2; // handled 2 more chars than usual
+          } else {
+            /*
+             * TODO: handle patterns that end in /. For now, ant's matching seem
+             * inconsistent.
+             * 
+             * ant pattern = testing/, path = testing/foo, result = true.
+             */
+            if (i == length - 1) {
+              return null;
+            }
+            sb.append(c);
+          }
+          break;
+        case '*':
+          // ** to .*
+          if (i + 1 < length && antPatternString.charAt(i + 1) == '*') {
+            if (i + 2 < length && antPatternString.charAt(i + 2) == '/') {
+              if (i == 0) {
+                /*
+                 * When a pattern does not start with a File.separator, the
+                 * string to match may not start with a File.separator.
+                 */
+                sb.append("([^/]+/)*");
+              } else {
+                // convert **/ to ([^/]*/)*
+                sb.append("([^/]*/)*");
+              }
+              i += 2;
+            } else {
+              if (i == 0) {
+                /*
+                 * When a pattern does not start with a File.separator, the
+                 * string to match may not start with a File.separator.
+                 */
+                sb.append("([^/].*)*");
+              } else {
+                sb.append(".*");
+              }
+              i++;
+            }
+          } else {
+            sb.append("[^/]*");
+          }
+          break;
+        default:
+          sb.append(c);
+          break;
+      }
+    }
+    return sb.toString();
+  }
+
+  /**
+   * Obtain the appropriate resourceFilter based on defaultExcludes and isJava
+   * values. Assumptions: caseSensitive = true,and the includesList and
+   * excludesList are empty
+   */
+  private ResourceFilter getMatchingDefaultFilter(boolean defaultExcludes,
+      boolean isJava) {
+    if (defaultExcludes) {
+      return isJava ? defaultJavaFilter : defaultResourceFilter;
+    }
+    return isJava ? justJavaFilter : justResourceFilter;
+  }
+
+  private Pattern getPatternFromAntStrings(String... antPatterns) {
+    String patternStrings[] = new String[antPatterns.length];
+    int count = 0;
+    for (String antPatternString : antPatterns) {
+      String patternString = getPatternFromAntPattern(antPatternString);
+      if (patternString == null) {
+        throw new RuntimeException("Unable to convert " + antPatternString
+            + " to java code");
+      }
+      patternStrings[count++] = patternString;
+    }
+    return getPatternFromStrings(patternStrings);
+  }
+
+  private Pattern getPatternFromStrings(String... patterns) {
+    StringBuffer entirePattern = new StringBuffer("^");
+    int length = patterns.length;
+    int count = 0;
+    for (String pattern : patterns) {
+      entirePattern.append("(" + pattern + ")");
+      if (count < length - 1) {
+        entirePattern.append("|");
+      }
+      count++;
+    }
+    entirePattern.append("$");
+    return Pattern.compile(entirePattern.toString());
+  }
+
+  private boolean isJavaFile(String path) {
+    return path.endsWith(".java");
+  }
+}
diff --git a/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java b/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java
new file mode 100644
index 0000000..3059de3
--- /dev/null
+++ b/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.resource.impl;
+
+import junit.framework.TestCase;
+
+import org.apache.tools.ant.types.ZipScanner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * An implementation for DefaultExcludesFilterTest.
+ * 
+ * Tests:
+ * 
+ * 1. The filter conversion from ant to Java regex. Which cases can we handle,
+ * and confirm that we perform correctly in all cases.
+ * 
+ * 2. checking the 4 defaultFilters, one for each combination of defaultExcludes
+ * and isJava.
+ * 
+ * 3. Checking whether customFilter work correctly, both in presence and absence
+ * of Ant.
+ * 
+ * TODO (amitmanjhi): clean up this test code.
+ */
+public class DefaultFiltersTest extends TestCase {
+
+  static class AdvancedPaths {
+    String baseIncluded[] = {
+        "Baz", "test/foo/Foo", "test/bar/Bar", "test/baz/Foo"};
+
+    String baseExcludedTesting[] = {"foo/testing/Baz"};
+    String baseExcludedExact[] = {"Foo", "Bar",};
+    String baseExcludedDoubleStar[] = {"fooz/Baz", "barz/hello/Baz"};
+    String baseExcluded[] = mergeArrays(baseExcludedTesting, baseExcludedExact,
+        baseExcludedDoubleStar);
+
+    void testAdvancedJavaPath(ResourceFilterString expected,
+        ResourceFilterString actual) {
+      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
+          "testing", false).toArray(EMPTY_ARRAY),
+          getMiscPaths("a/bc/de", false).toArray(EMPTY_ARRAY))) {
+        assertEquals(path + ".java", expected, actual);
+      }
+    }
+
+    void testAdvancedJavaPathAnt(ResourceFilterString expected,
+        ResourceFilterString actual) {
+      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
+          "testing", true).toArray(EMPTY_ARRAY),
+          getMiscPaths("a/bc/de", true).toArray(EMPTY_ARRAY))) {
+        assertEquals(excludedChars + path + excludedChars + javaSuffix,
+            expected, actual);
+        assertEquals(path + excludedChars + javaSuffix, expected, actual);
+        assertEquals(path + javaSuffix, expected, actual);
+      }
+      testAdvancedJavaPath(expected, actual);
+      new BasicPaths().testBasicJavaPath(expected, actual);
+    }
+
+    void testAdvancedPath(ResourceFilterString expected,
+        ResourceFilterString actual) {
+      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
+          "testing", false).toArray(EMPTY_ARRAY),
+          getMiscPaths("a/bc/de", false).toArray(EMPTY_ARRAY))) {
+        assertEquals(path, expected, actual);
+      }
+    }
+
+    void testAdvancedPathAnt(ResourceFilterString expected,
+        ResourceFilterString actual) {
+      for (String path : mergeArrays(baseIncluded, baseExcluded, getMiscPaths(
+          "testing", true).toArray(EMPTY_ARRAY),
+          getMiscPaths("a/bc/de", true).toArray(EMPTY_ARRAY))) {
+        assertEquals(path, expected, actual);
+        assertEquals(path + excludedChars, expected, actual);
+        assertEquals(excludedChars + path + excludedChars, expected, actual);
+      }
+      testAdvancedPath(expected, actual);
+      new BasicPaths().testBasicPath(expected, actual);
+    }
+  }
+
+  static class BasicPaths {
+    String baseIncluded[] = {
+        "foo", "/foo", "foo/bar", "/foo/bar", "/foo/bar", "/foo$/$", "/foo-_",
+        "123FOO123", "cvs", "cvs/cvs/svn", ".foo_bar$", "foo/asvn"};
+    String baseExcluded[] = {"foo/CVS/bar", "foo/.svn/bar", "foo/SCCS/bar",};
+    String baseSuffixExcluded[] = {
+        "foo/.cvsignore", "foo/CVS", "foo/.svn", "foo/SCCS",
+        "foo/bar/vssver.scc", "/foo/bar/.DS_Store"};
+
+    void testBasicJavaPath(ResourceFilterString expected,
+        ResourceFilterString actual) {
+      for (String str : mergeArrays(baseIncluded, baseExcluded,
+          baseSuffixExcluded,
+          getMiscPaths("testing", true).toArray(EMPTY_ARRAY), getMiscPaths(
+              "a/bc/de", true).toArray(EMPTY_ARRAY))) {
+        assertEquals(str, expected, actual);
+        assertEquals(str + javaSuffix, expected, actual);
+        assertEquals(excludedChars + str, expected, actual);
+        assertEquals(excludedChars + str + excludedChars, expected, actual);
+        assertEquals(excludedChars + str + javaSuffix, expected, actual);
+        assertEquals(excludedChars + str + excludedChars + javaSuffix,
+            expected, actual);
+      }
+    }
+
+    void testBasicPath(ResourceFilterString expected,
+        ResourceFilterString actual) {
+      for (String str : mergeArrays(baseIncluded, baseExcluded,
+          baseSuffixExcluded,
+          getMiscPaths("testing", true).toArray(EMPTY_ARRAY), getMiscPaths(
+              "a/bc/de", true).toArray(EMPTY_ARRAY))) {
+        assertEquals(str, expected, actual);
+        assertEquals(excludedChars + str, expected, actual);
+        assertEquals(excludedChars + str + excludedChars, expected, actual);
+      }
+    }
+  }
+
+  /*
+   * Sole purpose of this class is to get a useful debug message.
+   */
+  private static class ResourceFilterString {
+    final ResourceFilter filter;
+    final String stringRepresentation;
+
+    ResourceFilterString(ResourceFilter filter, String stringRepresentation) {
+      this.filter = filter;
+      this.stringRepresentation = stringRepresentation;
+    }
+
+  }
+
+  private static final String EMPTY_ARRAY[] = new String[0];
+  private static final boolean DEFAULT_EXCLUDES = true;
+  private static final boolean DEFAULT_INCLUDES = false;
+  private static final boolean NOT_JAVA = false;
+  private static final boolean YES_JAVA = true;
+
+  private static final String mergedPatterns[] = {
+      "**/testing/**", "Foo", "Bar", "fooz/**", "barz/hello/**"};
+
+  // careful that the pattern is still permitted by ant.
+  private static final String excludedChars = "#~%*";
+
+  private static final String javaSuffix = ".java";
+
+  private static void assertEquals(String path, ResourceFilterString expected,
+      ResourceFilterString actual) {
+    boolean scanResult = expected.filter.allows(path);
+    assertEquals("String to be matched = " + path + ", actual filter = "
+        + actual.stringRepresentation + " should yied " + scanResult
+        + ", expected Filter = " + expected.stringRepresentation, scanResult,
+        actual.filter.allows(path));
+  }
+
+  private static List<String> getMiscPaths(String middleString,
+      boolean endInSlash) {
+    List<String> testPaths = new ArrayList<String>();
+    testPaths.addAll(Arrays.asList(new String[] {
+        "Foo", "Bar", "foo/xyz", "afoo/xyz-_$", "b/foo/x",
+        "foo/BarTestabc.java", "foo/xyz/BarTestabc.java", "a/b/testing/c/d",
+        "a/testing/b/c/FooBazBarTest.java", "a/testing/b/Foo/BazBar.java",
+        "a/testing/b/Foo$-_$Bar.class", "a/testing/b/Foo$/$.class"}));
+
+    String pathPrefixes[] = {"", "/", "foo/", "/foo/", "bar/foo/", "/bar/foo/"};
+    List<String> pathSuffixes = new ArrayList<String>();
+    if (endInSlash) {
+      // special handling because currently we don't handle paths that end in /
+      pathSuffixes.addAll(Arrays.asList(new String[] {
+          "", "/", "/foo", "/foo/", "/foo/bar", "/foo/bar/"}));
+    } else {
+      pathSuffixes.addAll(Arrays.asList(new String[] {"", "/foo", "/foo/bar",}));
+    }
+    for (String pathPrefix : pathPrefixes) {
+      for (String pathSuffix : pathSuffixes) {
+        testPaths.add(pathPrefix + middleString + pathSuffix);
+      }
+    }
+    return testPaths;
+  }
+
+  private static String[] mergeArrays(String[]... baseArrays) {
+    int count = 0;
+    for (String arrayElement[] : baseArrays) {
+      count += arrayElement.length;
+    }
+    String retArray[] = new String[count];
+    count = 0;
+    for (String arrayElement[] : baseArrays) {
+      for (String element : arrayElement) {
+        retArray[count++] = element;
+      }
+    }
+    return retArray;
+  }
+
+  public void testEmptyFilters() {
+    BasicPaths basicPaths = new BasicPaths();
+    DefaultFilters defaultFilters = new DefaultFilters();
+
+    // first arg: ant filter, second arg: our custom filter
+    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
+        DEFAULT_EXCLUDES, NOT_JAVA, "antDefaultFilter"),
+        new ResourceFilterString(defaultFilters.defaultResourceFilter,
+            "defaultFilter"));
+    basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
+        DEFAULT_INCLUDES, NOT_JAVA, "antDefaultIncludesFilter"),
+        new ResourceFilterString(defaultFilters.justResourceFilter,
+            "defaultIncludesFilter"));
+
+    basicPaths.testBasicJavaPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
+        DEFAULT_EXCLUDES, YES_JAVA, "antDefaultJavaFilter"),
+        new ResourceFilterString(defaultFilters.defaultJavaFilter,
+            "defaultJavaFilter"));
+    basicPaths.testBasicJavaPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
+        DEFAULT_INCLUDES, YES_JAVA, "antJustJavaFilter"),
+        new ResourceFilterString(defaultFilters.justJavaFilter,
+            "justJavaFilter"));
+  }
+
+  /**
+   * (a) test that filters are correctly converted to non-null and null
+   * patterns. (b) test that filters match the same String.
+   */
+  public void testFilterConversion() {
+    List<String> nullFilters = Arrays.asList(new String[] {
+        "***/testing/**", "**/{/**", "**/}/**", "**/+/**", "**/testing/",
+        "**/testing/**/"});
+    List<String> okayFilters = new ArrayList<String>();
+    okayFilters.addAll(Arrays.asList(new String[] {
+        "**/#/**", "**/~/**", "Foo", "Bar", "foo/**", "foo/*Test*java",
+        "**/testing/**", "**/testing/**/Foo*Bar*.java",
+        "**/testing/**/Foo$*r.class",}));
+    String doubleStarPrefixes[] = {"", "/", "**/", "/**/", "foo**/", "/foo**/"};
+    // TODO: uncomment when we handle prefixes that end in /
+    // String doubleStarSuffixes[] = {"", "/", "/**", "/**/", "/**foo",
+    // "/**foo/"};
+    String doubleStarSuffixes[] = {"", "/**", "/**foo"};
+    String middleString = "testing";
+    for (String doubleStarPrefix : doubleStarPrefixes) {
+      for (String doubleStarSuffix : doubleStarSuffixes) {
+        okayFilters.add(doubleStarPrefix + middleString + doubleStarSuffix);
+      }
+    }
+
+    List<String> testPaths = getMiscPaths("testing", false);
+    /*
+     * TODO: investigate inconsistencies.
+     * 
+     * ant pattern = testing/, path = testing/foo, result = true.
+     */
+    DefaultFilters filters = new DefaultFilters();
+    for (String filter : nullFilters) {
+      assertNull(filter + " conversion should be null",
+          filters.getPatternFromAntPattern(filter));
+    }
+
+    for (String filter : okayFilters) {
+      String pattern = filters.getPatternFromAntPattern(filter);
+      assertNotNull(filter + " conversion should be non-null", pattern);
+
+      ResourceFilterString antFilterString = getAntFilter(
+          new String[] {filter}, EMPTY_ARRAY, DEFAULT_EXCLUDES, NOT_JAVA, "ant_"
+              + filter);
+      ResourceFilterString customFilterString = new ResourceFilterString(
+          filters.customFilterWithCatchAll(new String[] {filter}, EMPTY_ARRAY,
+              true, null, NOT_JAVA), "custom_" + pattern);
+      for (String path : testPaths) {
+        assertEquals(path, antFilterString, customFilterString);
+      }
+    }
+  }
+
+  public void testFilterParts() {
+    AdvancedPaths advancedPaths = new AdvancedPaths();
+    ResourceFilter filter = null;
+
+    // everything except those starting with '/' should be included
+    filter = new DefaultFilters().getFilterPart(EMPTY_ARRAY, true);
+    advancedPaths.testAdvancedPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
+        DEFAULT_INCLUDES, NOT_JAVA, "antDefaultFilter"),
+        new ResourceFilterString(filter, "defaultFilter"));
+
+    // everything should be excluded
+    filter = new DefaultFilters().getFilterPart(EMPTY_ARRAY, false);
+    advancedPaths.testAdvancedPath(getAntFilter(new String[] {"a/1/2/3"},
+        new String[] {"**", "/**"}, DEFAULT_INCLUDES, NOT_JAVA,
+        "antDefaultFilter"), new ResourceFilterString(filter, "defaultFilter"));
+
+    filter = new DefaultFilters().getFilterPart(mergedPatterns, true);
+    advancedPaths.testAdvancedPath(getAntFilter(mergedPatterns, EMPTY_ARRAY,
+        DEFAULT_INCLUDES, NOT_JAVA, "antMergedPatterns"),
+        new ResourceFilterString(filter, "customMergedPatterns"));
+  }
+
+  // no ant, catchAll filter is null
+  public void testNonEmptyFilters() {
+    AdvancedPaths advancedPaths = new AdvancedPaths();
+
+    ResourceFilter filter = null;
+    // pass empty includeArray. Matches everything that is not excluded.
+    filter = getFilterWithoutCatchAll(EMPTY_ARRAY, mergedPatterns, NOT_JAVA);
+    advancedPaths.testAdvancedPath(getAntFilter(EMPTY_ARRAY, mergedPatterns,
+        DEFAULT_EXCLUDES, NOT_JAVA, "ant_emptyArray_mergedPatterns"),
+        new ResourceFilterString(filter, "custom_emptyArray_mergedPatterns"));
+
+    // pass empty excludeArray. Matches everything that is included.
+    filter = getFilterWithoutCatchAll(mergedPatterns, EMPTY_ARRAY, NOT_JAVA);
+    advancedPaths.testAdvancedPath(getAntFilter(mergedPatterns, EMPTY_ARRAY,
+        DEFAULT_EXCLUDES, NOT_JAVA, "ant_mergedPatterns_emptyArray"),
+        new ResourceFilterString(filter, "custom_mergedPatterns_emptyArray"));
+
+    // pass non-empty include and exclude array. Matches nothing
+    filter = getFilterWithoutCatchAll(mergedPatterns, mergedPatterns, NOT_JAVA);
+    advancedPaths.testAdvancedPath(
+        getAntFilter(mergedPatterns, mergedPatterns, DEFAULT_EXCLUDES, NOT_JAVA,
+            "ant_mergedPatterns_mergedPatterns"),
+        new ResourceFilterString(filter, "custom_mergedPatterns_mergedPatterns"));
+  }
+
+  // finish, catchAll filter is not-null
+  public void testNonEmptyFiltersAnt() {
+    AdvancedPaths advancedPaths = new AdvancedPaths();
+
+    ResourceFilter filter = null;
+    // pass empty includeArray. Matches everything that is not excluded.
+    filter = getFilterWithCatchAll(EMPTY_ARRAY, mergedPatterns, NOT_JAVA);
+    advancedPaths.testAdvancedPathAnt(getAntFilter(EMPTY_ARRAY, mergedPatterns,
+        DEFAULT_EXCLUDES, NOT_JAVA, "ant_emptyArray_mergedPatterns"),
+        new ResourceFilterString(filter, "custom_emptyArray_mergedPatterns"));
+
+    // pass empty excludeArray. Matches everything that is included.
+    filter = getFilterWithCatchAll(mergedPatterns, EMPTY_ARRAY, NOT_JAVA);
+    advancedPaths.testAdvancedPathAnt(getAntFilter(mergedPatterns, EMPTY_ARRAY,
+        DEFAULT_EXCLUDES, NOT_JAVA, "ant_emptyArray_mergedPatterns"),
+        new ResourceFilterString(filter, "custom_emptyArray_mergedPatterns"));
+
+    // pass non-empty include and exclude array. Matches nothing
+    filter = getFilterWithCatchAll(mergedPatterns, mergedPatterns, NOT_JAVA);
+    advancedPaths.testAdvancedPathAnt(getAntFilter(mergedPatterns,
+        mergedPatterns, DEFAULT_EXCLUDES, NOT_JAVA,
+        "ant_mergedPatterns_mergedPatterns"), new ResourceFilterString(filter,
+        "custom_mergedPatterns_mergedPatterns"));
+  }
+
+  // no ant, catchAll filter is null
+  public void testNonEmptyJavaFilters() {
+    AdvancedPaths advancedPaths = new AdvancedPaths();
+
+    String newMergedPatterns[] = new String[mergedPatterns.length];
+    for (int i = 0; i < mergedPatterns.length; i++) {
+      if (mergedPatterns[i].endsWith("*")) {
+        newMergedPatterns[i] = mergedPatterns[i];
+      } else {
+        newMergedPatterns[i] = mergedPatterns[i] + ".java";
+      }
+    }
+    ResourceFilter filter = null;
+    // pass empty includeArray. Means catch all
+    filter = getFilterWithoutCatchAll(EMPTY_ARRAY, newMergedPatterns, YES_JAVA);
+    advancedPaths.testAdvancedJavaPath(getAntFilter(EMPTY_ARRAY,
+        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
+        "custom_emptyArray_newMergedPatterns"));
+
+    // pass empty excludeArray. Means catch only the pattern
+    filter = getFilterWithoutCatchAll(newMergedPatterns, EMPTY_ARRAY, YES_JAVA);
+    advancedPaths.testAdvancedJavaPath(getAntFilter(newMergedPatterns,
+        EMPTY_ARRAY, DEFAULT_EXCLUDES, YES_JAVA,
+        "ant_newMergedPatterns_emptyArray"), new ResourceFilterString(filter,
+        "custom_newMergedPatterns_emptyArray"));
+
+    // pass non-empty include and exclude array.
+    filter = getFilterWithoutCatchAll(newMergedPatterns, newMergedPatterns,
+        YES_JAVA);
+    advancedPaths.testAdvancedJavaPath(getAntFilter(newMergedPatterns,
+        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
+        filter, "custom_newMergedPatterns_newMergedPatterns"));
+  }
+
+  public void testNonEmptyJavaFiltersAnt() {
+    AdvancedPaths advancedPaths = new AdvancedPaths();
+
+    String newMergedPatterns[] = new String[mergedPatterns.length];
+    for (int i = 0; i < mergedPatterns.length; i++) {
+      if (mergedPatterns[i].endsWith("*")) {
+        newMergedPatterns[i] = mergedPatterns[i];
+      } else {
+        newMergedPatterns[i] = mergedPatterns[i] + ".java";
+      }
+    }
+    ResourceFilter filter = null;
+    // pass empty includeArray. Means catch all
+    filter = getFilterWithCatchAll(EMPTY_ARRAY, newMergedPatterns, YES_JAVA);
+    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(EMPTY_ARRAY,
+        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
+        "custom_emptyArray_newMergedPatterns"));
+
+    // pass empty excludeArray. Means catch only the pattern
+    filter = getFilterWithCatchAll(newMergedPatterns, EMPTY_ARRAY, YES_JAVA);
+    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
+        EMPTY_ARRAY, DEFAULT_EXCLUDES, YES_JAVA,
+        "ant_newMergedPatterns_emptyArray"), new ResourceFilterString(filter,
+        "custom_newMergedPatterns_emptyArray"));
+
+    // pass non-empty include and exclude array.
+    filter = getFilterWithCatchAll(newMergedPatterns, newMergedPatterns,
+        YES_JAVA);
+    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
+        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
+        filter, "custom_newMergedPatterns_newMergedPatterns"));
+  }
+
+  private ResourceFilterString getAntFilter(String includes[],
+      String excludes[], boolean defaultExcludes, final boolean isJava,
+      String tag) {
+    final ZipScanner scanner = DefaultFilters.getScanner(includes, excludes,
+        defaultExcludes, true);
+    return new ResourceFilterString(new ResourceFilter() {
+      public boolean allows(String path) {
+        if (isJava && !path.endsWith(".java")) {
+          return false;
+        }
+        return scanner.match(path);
+      }
+    }, tag != null ? tag : "includes: " + includes + ", excludes: " + excludes);
+  }
+
+  private ResourceFilter getFilterWithCatchAll(String includesList[],
+      String excludesList[], boolean isJava) {
+    if (isJava) {
+      return new DefaultFilters().customJavaFilter(includesList, excludesList,
+          true, true);
+    }
+    return new DefaultFilters().customResourceFilter(includesList,
+        excludesList, true, true);
+  }
+
+  // caseSensitive and excludeDefaults are set
+  private ResourceFilter getFilterWithoutCatchAll(String includesList[],
+      String excludesList[], boolean isJava) {
+    return new DefaultFilters().customFilterWithCatchAll(includesList,
+        excludesList, true, null, isJava);
+  }
+}
