Revision: 8554
Author: [email protected]
Date: Tue Aug 17 08:14:13 2010
Log: Allow merging of modules with the same prefix, for example if you have a
directory of widgets that are separated into multiple modules (but in the
same java package), or if you have src/test roots that each have modules
for the same package.  The existing "exclude" attribute is used to mark
something that no modue should ever touch, i.e. known non-translatable
source.  A new "skip" attribute is used to mark something that *this*
module doesn't want, but that *other* modules might need.  (You could
probably be clever with just include for this case, but sometimes it's
nice to be able to express a negative.)

Review at http://gwt-code-reviews.appspot.com/754802

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=8554

Added:
 /trunk/dev/core/test/com/google/gwt/dev/cfg/ModuleDefLoaderTest.java
 /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata
 /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging
 /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/One.gwt.xml
 /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/Three.gwt.xml
 /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/Two.gwt.xml
 /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client
/trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/InOne.java /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/InTwo.java /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/Shared.java /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/Toxic.java
Modified:
 /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
 /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
 /trunk/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java
 /trunk/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefix.java
 /trunk/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java
/trunk/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java

=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/ModuleDefLoaderTest.java Tue Aug 17 08:14:13 2010
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010 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.cfg;
+
+import com.google.gwt.core.ext.TreeLogger;
+
+import junit.framework.TestCase;
+
+/**
+ * Test for the module def loading
+ */
+public class ModuleDefLoaderTest extends TestCase {
+
+  /**
+   * Test of merging multiple modules in the same package space.
+ * This exercises the interaction of include, exclude, and skip attributes.
+   */
+  public void testModuleMerging() throws Exception {
+    TreeLogger logger = TreeLogger.NULL;
+    ModuleDef one = ModuleDefLoader.loadFromClassPath(logger,
+        "com.google.gwt.dev.cfg.testdata.merging.One", false);
+ assertNotNull(one.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/InOne.java")); + assertNotNull(one.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/Shared.java")); + assertNull(one.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/InTwo.java")); + assertNull(one.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/Toxic.java"));
+
+    ModuleDef two = ModuleDefLoader.loadFromClassPath(logger,
+        "com.google.gwt.dev.cfg.testdata.merging.Two", false);
+ assertNotNull(two.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/InOne.java")); + assertNotNull(two.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/Shared.java")); + assertNotNull(two.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/InTwo.java")); + assertNull(two.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/Toxic.java"));
+
+    ModuleDef three = ModuleDefLoader.loadFromClassPath(logger,
+        "com.google.gwt.dev.cfg.testdata.merging.Three", false);
+ assertNotNull(three.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/InOne.java")); + assertNotNull(three.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/Shared.java")); + assertNull(three.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/InTwo.java")); + assertNull(three.findSourceFile("com/google/gwt/dev/cfg/testdata/merging/client/Toxic.java"));
+  }
+
+}
=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/One.gwt.xml Tue Aug 17 08:14:13 2010
@@ -0,0 +1,3 @@
+<module>
+  <source path="client" excludes="Toxic.java" skips="InTwo.java"/>
+</module>
=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/Three.gwt.xml Tue Aug 17 08:14:13 2010
@@ -0,0 +1,6 @@
+<module>
+ <!-- note that it is deliberate including Toxic.java here is overridden by
+       the exclusion in module One -->
+  <source path="client" includes="Shared.java,Toxic.java"/>
+  <inherits name="com.google.gwt.dev.cfg.testdata.merging.One"/>
+</module>
=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/Two.gwt.xml Tue Aug 17 08:14:13 2010
@@ -0,0 +1,4 @@
+<module>
+  <source path="client" includes="InTwo.java,Shared.java"/>
+  <inherits name="com.google.gwt.dev.cfg.testdata.merging.One"/>
+</module>
=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/InOne.java Tue Aug 17 08:14:13 2010
@@ -0,0 +1,5 @@
+package com.google.gwt.dev.cfg.testdata.merging.client;
+
+public class InOne {
+  // test class
+}
=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/InTwo.java Tue Aug 17 08:14:13 2010
@@ -0,0 +1,5 @@
+package com.google.gwt.dev.cfg.testdata.merging.client;
+
+public class InTwo {
+  // test class
+}
=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/Shared.java Tue Aug 17 08:14:13 2010
@@ -0,0 +1,5 @@
+package com.google.gwt.dev.cfg.testdata.merging.client;
+
+public class Shared {
+  // test class
+}
=======================================
--- /dev/null
+++ /trunk/dev/core/test/com/google/gwt/dev/cfg/testdata/merging/client/Toxic.java Tue Aug 17 08:14:13 2010
@@ -0,0 +1,5 @@
+package com.google.gwt.dev.cfg.testdata.merging.client;
+
+public class Toxic {
+  // test class
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java Fri Aug 6 12:01:02 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java Tue Aug 17 08:14:13 2010
@@ -154,40 +154,41 @@
   }

   public synchronized void addPublicPackage(String publicPackage,
-      String[] includeList, String[] excludeList, boolean defaultExcludes,
-      boolean caseSensitive) {
+      String[] includeList, String[] excludeList, String[] skipList,
+      boolean defaultExcludes, boolean caseSensitive) {

     if (lazyPublicOracle != null) {
       throw new IllegalStateException("Already normalized");
     }
     publicPrefixSet.add(new PathPrefix(publicPackage,
         defaultFilters.customResourceFilter(includeList, excludeList,
-            defaultExcludes, caseSensitive), true));
+            skipList, defaultExcludes, caseSensitive), true, excludeList));
   }

   public void addSourcePackage(String sourcePackage, String[] includeList,
- String[] excludeList, boolean defaultExcludes, boolean caseSensitive) {
+      String[] excludeList, String[] skipList, boolean defaultExcludes,
+      boolean caseSensitive) {
     addSourcePackageImpl(sourcePackage, includeList, excludeList,
-        defaultExcludes, caseSensitive, false);
+        skipList, defaultExcludes, caseSensitive, false);
   }

public void addSourcePackageImpl(String sourcePackage, String[] includeList,
-      String[] excludeList, boolean defaultExcludes, boolean caseSensitive,
-      boolean isSuperSource) {
+      String[] excludeList, String[] skipList, boolean defaultExcludes,
+      boolean caseSensitive, boolean isSuperSource) {
     if (lazySourceOracle != null) {
       throw new IllegalStateException("Already normalized");
     }
     PathPrefix pathPrefix = new PathPrefix(sourcePackage,
-        defaultFilters.customJavaFilter(includeList, excludeList,
-            defaultExcludes, caseSensitive), isSuperSource);
+        defaultFilters.customJavaFilter(includeList, excludeList, skipList,
+            defaultExcludes, caseSensitive), isSuperSource, excludeList);
     sourcePrefixSet.add(pathPrefix);
   }

   public void addSuperSourcePackage(String superSourcePackage,
-      String[] includeList, String[] excludeList, boolean defaultExcludes,
-      boolean caseSensitive) {
+      String[] includeList, String[] excludeList, String[] skipList,
+      boolean defaultExcludes, boolean caseSensitive) {
     addSourcePackageImpl(superSourcePackage, includeList, excludeList,
-        defaultExcludes, caseSensitive, true);
+        skipList, defaultExcludes, caseSensitive, true);
   }

   /**
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java Mon Jun 7 12:20:31 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java Tue Aug 17 08:14:13 2010
@@ -1,12 +1,12 @@
 /*
  * 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
@@ -93,9 +93,11 @@

     protected final String __public_3_excludes = "";

-    protected final String __public_4_defaultexcludes = "yes";
-
-    protected final String __public_5_casesensitive = "true";
+    protected final String __public_4_skips = "";
+
+    protected final String __public_5_defaultexcludes = "yes";
+
+    protected final String __public_6_casesensitive = "true";

     protected final String __replace_with_1_class = null;

@@ -123,9 +125,11 @@

     protected final String __source_3_excludes = "";

-    protected final String __source_4_defaultexcludes = "yes";
-
-    protected final String __source_5_casesensitive = "true";
+    protected final String __source_4_skips = "";
+
+    protected final String __source_5_defaultexcludes = "yes";
+
+    protected final String __source_6_casesensitive = "true";

     protected final String __stylesheet_1_src = null;

@@ -135,9 +139,11 @@

     protected final String __super_source_3_excludes = "";

-    protected final String __super_source_4_defaultexcludes = "yes";
-
-    protected final String __super_source_5_casesensitive = "true";
+    protected final String __super_source_4_skips = "";
+
+    protected final String __super_source_5_defaultexcludes = "yes";
+
+    protected final String __super_source_6_casesensitive = "true";

     /**
      * Used to accumulate binding property conditions before recording the
@@ -433,12 +439,13 @@

     @SuppressWarnings("unused")
     protected Schema __public_begin(String path, String includes,
-        String excludes, String defaultExcludes, String caseSensitive) {
+        String excludes, String skips, String defaultExcludes,
+        String caseSensitive) {
       return fChild = new IncludeExcludeSchema();
     }

protected void __public_end(String path, String includes, String excludes,
-        String defaultExcludes, String caseSensitive) {
+        String skips, String defaultExcludes, String caseSensitive) {
       IncludeExcludeSchema childSchema = ((IncludeExcludeSchema) fChild);
       foundAnyPublic = true;

@@ -450,11 +457,15 @@
       addDelimitedStringToSet(excludes, "[ ,]", excludeSet);
String[] excludeList = excludeSet.toArray(new String[excludeSet.size()]);

+      Set<String> skipSet = childSchema.getSkips();
+      addDelimitedStringToSet(skips, "[ ,]", skipSet);
+      String[] skipList = skipSet.toArray(new String[skipSet.size()]);
+
       boolean doDefaultExcludes = toPrimitiveBoolean(defaultExcludes);
       boolean doCaseSensitive = toPrimitiveBoolean(caseSensitive);

       addPublicPackage(modulePackageAsPath, path, includeList, excludeList,
-          doDefaultExcludes, doCaseSensitive);
+          skipList, doDefaultExcludes, doCaseSensitive);
     }

     protected Schema __replace_with_begin(String className) {
@@ -591,13 +602,14 @@
      */
     @SuppressWarnings("unused")
     protected Schema __source_begin(String path, String includes,
-        String excludes, String defaultExcludes, String caseSensitive) {
+        String excludes, String skips, String defaultExcludes,
+        String caseSensitive) {
       return fChild = new IncludeExcludeSchema();
     }

protected void __source_end(String path, String includes, String excludes,
-        String defaultExcludes, String caseSensitive) {
-      addSourcePackage(path, includes, excludes, defaultExcludes,
+        String skips, String defaultExcludes, String caseSensitive) {
+      addSourcePackage(path, includes, excludes, skips, defaultExcludes,
           caseSensitive, false);
     }

@@ -616,13 +628,15 @@
      */
     @SuppressWarnings("unused")
     protected Schema __super_source_begin(String path, String includes,
-        String excludes, String defaultExcludes, String caseSensitive) {
+        String excludes, String skips, String defaultExcludes,
+        String caseSensitive) {
       return fChild = new IncludeExcludeSchema();
     }

     protected void __super_source_end(String path, String includes,
-        String excludes, String defaultExcludes, String caseSensitive) {
-      addSourcePackage(path, includes, excludes, defaultExcludes,
+        String excludes, String skips, String defaultExcludes,
+        String caseSensitive) {
+      addSourcePackage(path, includes, excludes, skips, defaultExcludes,
           caseSensitive, true);
     }

@@ -639,8 +653,8 @@
     }

     private void addPublicPackage(String parentDir, String relDir,
- String[] includeList, String[] excludeList, boolean defaultExcludes,
-        boolean caseSensitive) {
+        String[] includeList, String[] excludeList, String[] skipList,
+        boolean defaultExcludes, boolean caseSensitive) {
       String normChildDir = normalizePathEntry(relDir);
       if (normChildDir.startsWith("/")) {
         logger.log(TreeLogger.WARN, "Non-relative public package: "
@@ -658,13 +672,13 @@
         return;
       }
       String fullDir = parentDir + normChildDir;
-      moduleDef.addPublicPackage(fullDir, includeList, excludeList,
+ moduleDef.addPublicPackage(fullDir, includeList, excludeList, skipList,
           defaultExcludes, caseSensitive);
     }

     private void addSourcePackage(String relDir, String includes,
-        String excludes, String defaultExcludes, String caseSensitive,
-        boolean isSuperSource) {
+        String excludes, String skips, String defaultExcludes,
+        String caseSensitive, boolean isSuperSource) {
       IncludeExcludeSchema childSchema = ((IncludeExcludeSchema) fChild);
       foundExplicitSourceOrSuperSource = true;

@@ -676,16 +690,20 @@
       addDelimitedStringToSet(excludes, "[ ,]", excludeSet);
String[] excludeList = excludeSet.toArray(new String[excludeSet.size()]);

+      Set<String> skipSet = childSchema.getSkips();
+      addDelimitedStringToSet(skips, "[ ,]", skipSet);
+      String[] skipList = skipSet.toArray(new String[skipSet.size()]);
+
       boolean doDefaultExcludes = toPrimitiveBoolean(defaultExcludes);
       boolean doCaseSensitive = toPrimitiveBoolean(caseSensitive);

addSourcePackage(modulePackageAsPath, relDir, includeList, excludeList,
-          doDefaultExcludes, doCaseSensitive, isSuperSource);
+          skipList, doDefaultExcludes, doCaseSensitive, isSuperSource);
     }

     private void addSourcePackage(String modulePackagePath, String relDir,
- String[] includeList, String[] excludeList, boolean defaultExcludes,
-        boolean caseSensitive, boolean isSuperSource) {
+        String[] includeList, String[] excludeList, String[] skipList,
+ boolean defaultExcludes, boolean caseSensitive, boolean isSuperSource) {
       String normChildDir = normalizePathEntry(relDir);
       if (normChildDir.startsWith("/")) {
         logger.log(TreeLogger.WARN, "Non-relative source package: "
@@ -711,18 +729,19 @@
          * logical class names.
          */
         moduleDef.addSuperSourcePackage(fullPackagePath, includeList,
-            excludeList, defaultExcludes, caseSensitive);
+            excludeList, skipList, defaultExcludes, caseSensitive);
       } else {
         /*
- * Add the full package path to the include and exclude lists since the + * Add the full package path to the include/exclude/skip lists since the * logical name of classes on the source path includes the package path
-         * but the include and exclude lists do not.
+         * but the include, exclude, and skip lists do not.
          */
         addPrefix(includeList, fullPackagePath);
         addPrefix(excludeList, fullPackagePath);
+        addPrefix(skipList, fullPackagePath);

moduleDef.addSourcePackage(fullPackagePath, includeList, excludeList,
-            defaultExcludes, caseSensitive);
+            skipList, defaultExcludes, caseSensitive);
       }
     }

@@ -805,10 +824,23 @@

     protected final String __include_1_name = null;

+    protected final String __skip_1_name = null;
+
+    /**
+     * Files neither in this module, nor available from other modules.
+     */
     private final Set<String> excludes = new HashSet<String>();

+    /**
+     * Files in this module.
+     */
     private final Set<String> includes = new HashSet<String>();

+    /**
+     * Files not in this module, but available from other modules.
+     */
+    private final Set<String> skips = new HashSet<String>();
+
     public Set<String> getExcludes() {
       return excludes;
     }
@@ -816,6 +848,10 @@
     public Set<String> getIncludes() {
       return includes;
     }
+
+    public Set<String> getSkips() {
+      return skips;
+    }

     protected Schema __exclude_begin(String name) {
       excludes.add(name);
@@ -826,7 +862,12 @@
       includes.add(name);
       return null;
     }
-  }
+
+    protected Schema __skip_begin(String name) {
+      skips.add(name);
+      return null;
+    }
+}

   private static class LinkerName {
     public final String name;
@@ -1231,12 +1272,12 @@
     //
     if (!foundExplicitSourceOrSuperSource) {
bodySchema.addSourcePackage(modulePackageAsPath, "client", Empty.STRINGS,
-          Empty.STRINGS, true, true, false);
+          Empty.STRINGS, Empty.STRINGS, true, true, false);
     }

     if (!foundAnyPublic) {
bodySchema.addPublicPackage(modulePackageAsPath, "public", Empty.STRINGS,
-          Empty.STRINGS, true, true);
+          Empty.STRINGS, Empty.STRINGS, true, true);
     }

     // We do this in __module_end so this value is never inherited
@@ -1246,7 +1287,7 @@
   /**
* Parses handwritten JavaScript found in the module xml, logging an error
    * message and throwing an exception if there's a problem.
-   *
+   *
* @param startLineNumber the start line number where the script was found;
    *          used to report errors
* @param script the JavaScript to wrap in "function() { script }" to parse
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java Wed Oct 28 09:10:53 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/resource/impl/DefaultFilters.java Tue Aug 17 08:14:13 2010
@@ -44,7 +44,7 @@
   private static final boolean YES_JAVA = true;

   static ZipScanner getScanner(String[] includeList, String[] excludeList,
-      boolean defaultExcludes, boolean caseSensitive) {
+      String[] skipList, 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
@@ -54,8 +54,9 @@
     if (includeList.length > 0) {
       scanner.setIncludes(includeList);
     }
-    if (excludeList.length > 0) {
-      scanner.setExcludes(excludeList);
+    if (excludeList.length > 0 || skipList.length > 0) {
+      String[] excludeOrSkip = concatenate(excludeList, skipList);
+      scanner.setExcludes(excludeOrSkip);
     }
     if (defaultExcludes) {
       scanner.addDefaultExcludes();
@@ -66,6 +67,18 @@
     return scanner;
   }

+  private static String[] concatenate(String[] array1, String[] array2) {
+    String[] answer = new String[array1.length + array2.length];
+    int i = 0;
+    for (String entry : array1) {
+      answer[i++] = entry;
+    }
+    for (String entry : array2) {
+      answer[i++] = entry;
+    }
+    return answer;
+  }
+
   /* used when defaultExcludes is true */
   final ResourceFilter defaultResourceFilter = new ResourceFilter() {

@@ -162,15 +175,17 @@
   }

   public ResourceFilter customJavaFilter(String includeList[],
- String excludeList[], boolean defaultExcludes, boolean caseSensitive) {
-    return getCustomFilter(includeList, excludeList, defaultExcludes,
+      String excludeList[], String skipList[], boolean defaultExcludes,
+      boolean caseSensitive) {
+ return getCustomFilter(includeList, excludeList, skipList, defaultExcludes,
         caseSensitive, YES_JAVA);
   }

   public ResourceFilter customResourceFilter(String includeList[],
- String excludeList[], boolean defaultExcludes, boolean caseSensitive) {
-
-    return getCustomFilter(includeList, excludeList, defaultExcludes,
+      String excludeList[], String[] skipList, boolean defaultExcludes,
+      boolean caseSensitive) {
+
+ return getCustomFilter(includeList, excludeList, skipList, defaultExcludes,
         caseSensitive, NOT_JAVA);
   }

@@ -180,13 +195,15 @@
    * 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 String excludeList[], final String skipList[],
+      final boolean defaultExcludes, final ResourceFilter catchAll,
+      final boolean isJava) {
+
+ assert includeList.length > 0 || excludeList.length > 0 || skipList.length > 0;

final ResourceFilter includeFilter = getFilterPart(includeList, IS_INCLUDES); - final ResourceFilter excludeFilter = getFilterPart(excludeList, IS_EXCLUDES); + final ResourceFilter excludeFilter = getFilterPart(concatenate(excludeList, skipList),
+        IS_EXCLUDES);

     if (includeFilter == null || excludeFilter == null) {
       return catchAll;
@@ -216,9 +233,11 @@
   }

   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) {
+      final String excludeList[], final String skipList[],
+      final boolean defaultExcludes, final boolean caseSensitive,
+      final boolean isJava) {
+    if (includeList.length == 0 && excludeList.length == 0 &&
+        skipList.length == 0 && caseSensitive) {
       // optimize for the common case.
       return getMatchingDefaultFilter(defaultExcludes, isJava);
     }
@@ -226,7 +245,7 @@
     // don't create a catchAll in default cases
     ResourceFilter catchAll = new ResourceFilter() {
       ZipScanner scanner = getScanner(includeList, excludeList,
-          defaultExcludes, caseSensitive);
+          skipList, defaultExcludes, caseSensitive);

       public boolean allows(String path) {
         if (isJava) {
@@ -240,7 +259,7 @@
     if (!caseSensitive) {
       return catchAll;
     }
- return customFilterWithCatchAll(includeList, excludeList, defaultExcludes, + return customFilterWithCatchAll(includeList, excludeList, skipList, defaultExcludes,
         catchAll, isJava);
   }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefix.java Fri Feb 6 13:06:24 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefix.java Tue Aug 17 08:14:13 2010
@@ -1,12 +1,12 @@
 /*
  * 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
@@ -15,6 +15,13 @@
  */
 package com.google.gwt.dev.resource.impl;

+import org.apache.tools.ant.types.ZipScanner;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 /**
  * Represents the abstract path prefix that goes between the
* {...@link ClassPathEntry} and the rest of resource's abstract path. This concept
@@ -31,14 +38,16 @@

   public static final PathPrefix ALL = new PathPrefix("", null);

-  private final ResourceFilter filter;
+  private final Set<String> exclusions;
+  private ZipScanner exclusionScanner;
+  private final List<ResourceFilter> filters;
   private final String prefix;
   private int priority = -1;
   private final boolean shouldReroot;

   /**
    * Construct a non-rerooting prefix.
-   *
+   *
* @param prefix a string prefix that (1) is the empty string or (2) begins
    *          with something other than a slash and ends with a slash
    * @param filter the resource filter to use, or <code>null</code> for no
@@ -47,12 +56,12 @@
    *          inconsistent behavior in identifying available resources)
    */
   public PathPrefix(String prefix, ResourceFilter filter) {
-    this(prefix, filter, false);
+    this(prefix, filter, false, null);
   }

   /**
-   * Construct a prefix.
-   *
+   * Construct a prefix without global exclusions.
+   *
* @param prefix a string prefix that (1) is the empty string or (2) begins
    *          with something other than a slash and ends with a slash
    * @param filter the resource filter to use, or <code>null</code> for no
@@ -63,19 +72,46 @@
* for this prefix will be rerooted to not include the initial prefix
    *          path; if <code>false</code>, the prefix will be included in a
    *          matching resource's path.
-   *
    */
public PathPrefix(String prefix, ResourceFilter filter, boolean shouldReroot) {
+    this(prefix, filter, shouldReroot, null);
+  }
+
+  /**
+   * Construct a prefix.
+   *
+ * @param prefix a string prefix that (1) is the empty string or (2) begins
+   *          with something other than a slash and ends with a slash
+   * @param filter the resource filter to use, or <code>null</code> for no
+ * filter; note that the filter must always return the same answer
+   *          for the same candidate path (doing otherwise will produce
+   *          inconsistent behavior in identifying available resources)
+ * @param shouldReroot if <code>true</code>, any matching {...@link Resource} + * for this prefix will be rerooted to not include the initial prefix
+   *          path; if <code>false</code>, the prefix will be included in a
+   *          matching resource's path.
+ * @param excludeList list of globs that should be removed from <i>any</i>
+   *          module's resources.
+   */
+ public PathPrefix(String prefix, ResourceFilter filter, boolean shouldReroot,
+      String[] excludeList) {
     assertValidPrefix(prefix);
     this.prefix = prefix;
-    this.filter = filter;
+    this.filters = new ArrayList<ResourceFilter>(1);
+    this.filters.add(filter);
     this.shouldReroot = shouldReroot;
+    this.exclusions = new HashSet<String>();
+    if (excludeList != null) {
+      for (String exclude : excludeList) {
+        exclusions.add(exclude);
+      }
+    }
   }

   /**
* Determines whether or not a given path is allowed by this path prefix by
    * checking both the prefix string and the filter.
-   *
+   *
    * @param path
    * @return
    */
@@ -83,13 +119,23 @@
     if (!path.startsWith(prefix)) {
       return false;
     }
-    if (filter == null) {
+    if (filters.size() == 0 && exclusions.size() == 0) {
       return true;
     }
     if (shouldReroot) {
       path = getRerootedPath(path);
     }
-    return filter.allows(path);
+
+    createExcludeFilter();
+    if (exclusionScanner != null && exclusionScanner.match(path)) {
+      return false;
+    }
+    for (ResourceFilter filter : filters) {
+      if (filter == null || filter.allows(path)) {
+        return true;
+      }
+    }
+    return false;
   }

   /**
@@ -108,7 +154,7 @@

   /**
    * The prefix.
-   *
+   *
    * @return the result is guaranteed to be non-<code>null</code>, and
* either be the empty string or it will not begin with a slash and
    *         will end with a slash; these guarantees are very useful when
@@ -131,6 +177,23 @@
   public int hashCode() {
     return prefix.hashCode();
   }
+
+  /**
+ * Consolidate a given {...@code PathPrefix} with this one, such that resources
+   * excluded by neither prefix and included by either are allowed.
+   *
+   * @param pathPrefix
+   */
+  public void merge(PathPrefix pathPrefix) {
+    assert prefix.equals(pathPrefix.prefix);
+    for (ResourceFilter filter : pathPrefix.filters) {
+      filters.add(filter);
+    }
+    exclusions.addAll(pathPrefix.exclusions);
+    if (exclusionScanner != null && !exclusions.isEmpty()) {
+      exclusionScanner = null;  // lose the stale one; we'll recreate later
+    }
+  }

   public boolean shouldReroot() {
     return shouldReroot;
@@ -138,7 +201,7 @@

   @Override
   public String toString() {
- return prefix + (shouldReroot ? "**" : "*") + (filter == null ? "" : "?"); + return prefix + (shouldReroot ? "**" : "*") + (filters.size() == 0 ? "" : "?");
   }

   int getPriority() {
@@ -154,4 +217,13 @@
     assert (prefix != null);
assert ("".equals(prefix) || (!prefix.startsWith("/") && prefix.endsWith("/"))) : "malformed prefix";
   }
-}
+
+  private void createExcludeFilter() {
+    if (exclusionScanner == null && !exclusions.isEmpty()) {
+      exclusionScanner = new ZipScanner();
+ exclusionScanner.setIncludes(exclusions.toArray(new String[exclusions.size()]));
+      exclusionScanner.init();
+      exclusions.clear();
+    }
+  }
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java Wed Apr 1 12:12:47 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java Tue Aug 17 08:14:13 2010
@@ -29,12 +29,7 @@
  */
 public class PathPrefixSet {
   /*
- * (1) TODO(amitmanjhi): Support multiple PathPrefixes with different filters
-   * but the same "path". This could arise when client code inherits some
- * library code and defines the same path prefix with a more specific resource
-   * filter.
-   *
- * (2) TODO(amitmanjhi): Improve the api of the PathPrefixSet so that with one + * (1) TODO(amitmanjhi): Improve the api of the PathPrefixSet so that with one * trie-traversal, it could be found out which resources rooted at a directory
    * are allowed?
    */
@@ -56,6 +51,14 @@
       children = Maps.put(children, part, newChild);
       return newChild;
     }
+
+    public void extendPathPrefix(PathPrefix prefix) {
+      if (this.prefix == null) {
+        this.prefix = prefix;
+      } else {
+        this.prefix.merge(prefix);
+      }
+    }

     public TrieNode findChild(String part) {
       return children.get(part);
@@ -68,10 +71,6 @@
     public boolean hasChildren() {
       return !children.isEmpty();
     }
-
-    public void setPathPrefix(PathPrefix prefix) {
-      this.prefix = prefix;
-    }

     @Override
     public String toString() {
@@ -103,9 +102,9 @@
   /**
    * @param prefix the prefix to add
    * @return <code>true</code> if the prefix was not already in the set;
- * otherwise, it replaced an identical one having the same prefix, - * which has the effect of changing which filter is used (last one
-   *         wins)
+ * otherwise, it merged with one having the same prefix, which has
+   *         the effect of expanding the filter (the merge works as
+   *         <code>union(includes - skips) - union(excludes)</code>)
    */
   public boolean add(PathPrefix prefix) {
     prefix.setPriority(prefixes.size());
@@ -118,7 +117,7 @@
      * prefix to the root so that we can apply the filter.
      */
     if ("".equals(pathPrefix)) {
-      rootTrieNode.setPathPrefix(prefix);
+      rootTrieNode.extendPathPrefix(prefix);
       return false;
     }

@@ -138,8 +137,7 @@
       }
     }
     assert (parentNode != null);
-    // This may clobber an existing one, but that's okay. Last one wins.
-    parentNode.setPathPrefix(prefix);
+    parentNode.extendPathPrefix(prefix);
     return didAdd;
   }

=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java Wed Oct 28 09:10:53 2009 +++ /trunk/dev/core/test/com/google/gwt/dev/resource/impl/DefaultFiltersTest.java Tue Aug 17 08:14:13 2010
@@ -219,20 +219,20 @@

     // first arg: ant filter, second arg: our custom filter
     basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
-        DEFAULT_EXCLUDES, NOT_JAVA, "antDefaultFilter"),
+        EMPTY_ARRAY, DEFAULT_EXCLUDES, NOT_JAVA, "antDefaultFilter"),
         new ResourceFilterString(defaultFilters.defaultResourceFilter,
             "defaultFilter"));
     basicPaths.testBasicPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
-        DEFAULT_INCLUDES, NOT_JAVA, "antDefaultIncludesFilter"),
+ EMPTY_ARRAY, DEFAULT_INCLUDES, NOT_JAVA, "antDefaultIncludesFilter"),
         new ResourceFilterString(defaultFilters.justResourceFilter,
             "defaultIncludesFilter"));

     basicPaths.testBasicJavaPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
-        DEFAULT_EXCLUDES, YES_JAVA, "antDefaultJavaFilter"),
+        EMPTY_ARRAY, DEFAULT_EXCLUDES, YES_JAVA, "antDefaultJavaFilter"),
         new ResourceFilterString(defaultFilters.defaultJavaFilter,
             "defaultJavaFilter"));
     basicPaths.testBasicJavaPath(getAntFilter(EMPTY_ARRAY, EMPTY_ARRAY,
-        DEFAULT_INCLUDES, YES_JAVA, "antJustJavaFilter"),
+        EMPTY_ARRAY, DEFAULT_INCLUDES, YES_JAVA, "antJustJavaFilter"),
         new ResourceFilterString(defaultFilters.justJavaFilter,
             "justJavaFilter"));
   }
@@ -270,11 +270,11 @@
       assertNotNull(filter + " conversion should be non-null", pattern);

       ResourceFilterString antFilterString = getAntFilter(
-          new String[] {filter}, EMPTY_ARRAY, DEFAULT_EXCLUDES, NOT_JAVA,
-          "ant_" + filter);
+ new String[] {filter}, EMPTY_ARRAY, 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);
+              EMPTY_ARRAY, true, null, NOT_JAVA), "custom_" + pattern);
       for (String path : testPaths) {
         assertEquals(path, antFilterString, customFilterString);
       }
@@ -288,18 +288,18 @@
     // 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"),
+        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,
+ new String[] {"**", "/**"}, EMPTY_ARRAY, 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"),
+        EMPTY_ARRAY, DEFAULT_INCLUDES, NOT_JAVA, "antMergedPatterns"),
         new ResourceFilterString(filter, "customMergedPatterns"));
   }

@@ -309,22 +309,25 @@

     ResourceFilter filter = null;
     // pass empty includeArray. Matches everything that is not excluded.
- filter = getFilterWithoutCatchAll(EMPTY_ARRAY, mergedPatterns, NOT_JAVA); + filter = getFilterWithoutCatchAll(EMPTY_ARRAY, mergedPatterns, EMPTY_ARRAY,
+        NOT_JAVA);
advancedPaths.testAdvancedPath(getAntFilter(EMPTY_ARRAY, mergedPatterns,
-        DEFAULT_EXCLUDES, NOT_JAVA, "ant_emptyArray_mergedPatterns"),
+ EMPTY_ARRAY, 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); + filter = getFilterWithoutCatchAll(mergedPatterns, EMPTY_ARRAY, EMPTY_ARRAY,
+        NOT_JAVA);
advancedPaths.testAdvancedPath(getAntFilter(mergedPatterns, EMPTY_ARRAY,
-        DEFAULT_EXCLUDES, NOT_JAVA, "ant_mergedPatterns_emptyArray"),
+ 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);
+    filter = getFilterWithoutCatchAll(mergedPatterns, mergedPatterns,
+        EMPTY_ARRAY, NOT_JAVA);
     advancedPaths.testAdvancedPath(
-        getAntFilter(mergedPatterns, mergedPatterns, DEFAULT_EXCLUDES,
-            NOT_JAVA, "ant_mergedPatterns_mergedPatterns"),
+        getAntFilter(mergedPatterns, mergedPatterns, EMPTY_ARRAY,
+ DEFAULT_EXCLUDES, NOT_JAVA, "ant_mergedPatterns_mergedPatterns"), new ResourceFilterString(filter, "custom_mergedPatterns_mergedPatterns"));
   }

@@ -334,21 +337,26 @@

     ResourceFilter filter = null;
     // pass empty includeArray. Matches everything that is not excluded.
-    filter = getFilterWithCatchAll(EMPTY_ARRAY, mergedPatterns, NOT_JAVA);
+ filter = getFilterWithCatchAll(EMPTY_ARRAY, mergedPatterns, EMPTY_ARRAY,
+        NOT_JAVA);
advancedPaths.testAdvancedPathAnt(getAntFilter(EMPTY_ARRAY, mergedPatterns,
-        DEFAULT_EXCLUDES, NOT_JAVA, "ant_emptyArray_mergedPatterns"),
+        EMPTY_ARRAY, 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);
+ filter = getFilterWithCatchAll(mergedPatterns, EMPTY_ARRAY, EMPTY_ARRAY,
+        NOT_JAVA);
advancedPaths.testAdvancedPathAnt(getAntFilter(mergedPatterns, EMPTY_ARRAY,
-        DEFAULT_EXCLUDES, NOT_JAVA, "ant_emptyArray_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); + filter = getFilterWithCatchAll(mergedPatterns, mergedPatterns, EMPTY_ARRAY,
+        NOT_JAVA);
     advancedPaths.testAdvancedPathAnt(getAntFilter(mergedPatterns,
-        mergedPatterns, DEFAULT_EXCLUDES, NOT_JAVA,
+        mergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, NOT_JAVA,
"ant_mergedPatterns_mergedPatterns"), new ResourceFilterString(filter,
         "custom_mergedPatterns_mergedPatterns"));
   }
@@ -367,24 +375,26 @@
     }
     ResourceFilter filter = null;
     // pass empty includeArray. Means catch all
- filter = getFilterWithoutCatchAll(EMPTY_ARRAY, newMergedPatterns, YES_JAVA);
+    filter = getFilterWithoutCatchAll(EMPTY_ARRAY, newMergedPatterns,
+        EMPTY_ARRAY, YES_JAVA);
     advancedPaths.testAdvancedJavaPath(getAntFilter(EMPTY_ARRAY,
-        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        newMergedPatterns, EMPTY_ARRAY, 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);
+    filter = getFilterWithoutCatchAll(newMergedPatterns, EMPTY_ARRAY,
+        EMPTY_ARRAY, YES_JAVA);
     advancedPaths.testAdvancedJavaPath(getAntFilter(newMergedPatterns,
-        EMPTY_ARRAY, DEFAULT_EXCLUDES, YES_JAVA,
+        EMPTY_ARRAY, 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);
+        EMPTY_ARRAY, YES_JAVA);
     advancedPaths.testAdvancedJavaPath(getAntFilter(newMergedPatterns,
-        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, YES_JAVA,
"ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
         filter, "custom_newMergedPatterns_newMergedPatterns"));
   }
@@ -402,33 +412,73 @@
     }
     ResourceFilter filter = null;
     // pass empty includeArray. Means catch all
- filter = getFilterWithCatchAll(EMPTY_ARRAY, newMergedPatterns, YES_JAVA); + filter = getFilterWithCatchAll(EMPTY_ARRAY, newMergedPatterns, EMPTY_ARRAY,
+        YES_JAVA);
     advancedPaths.testAdvancedJavaPathAnt(getAntFilter(EMPTY_ARRAY,
-        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        newMergedPatterns, EMPTY_ARRAY, 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); + filter = getFilterWithCatchAll(newMergedPatterns, EMPTY_ARRAY, EMPTY_ARRAY,
+        YES_JAVA);
     advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
-        EMPTY_ARRAY, DEFAULT_EXCLUDES, YES_JAVA,
+        EMPTY_ARRAY, 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,
+        EMPTY_ARRAY, YES_JAVA);
+    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
+        newMergedPatterns, EMPTY_ARRAY, DEFAULT_EXCLUDES, YES_JAVA,
+ "ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
+        filter, "custom_newMergedPatterns_newMergedPatterns"));
+  }
+
+  public void testNonEmptyJavaSkipFiltersAnt() {
+    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, skipping newMergedPatterns
+ filter = getFilterWithCatchAll(EMPTY_ARRAY, EMPTY_ARRAY, newMergedPatterns,
         YES_JAVA);
+    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(EMPTY_ARRAY,
+        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+ "ant_emptyArray_newMergedPatterns"), new ResourceFilterString(filter,
+        "custom_emptyArray_newMergedPatterns"));
+
+    // pass non-empty include and skip array.
+    filter = getFilterWithCatchAll(newMergedPatterns, EMPTY_ARRAY,
+        newMergedPatterns, YES_JAVA);
     advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
-        newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
+        EMPTY_ARRAY, newMergedPatterns, DEFAULT_EXCLUDES, YES_JAVA,
"ant_newMergedPatterns_newMergedPatterns"), new ResourceFilterString(
         filter, "custom_newMergedPatterns_newMergedPatterns"));
+
+    // in a single filter, skip and exclude are equivalent
+    filter = getFilterWithCatchAll(newMergedPatterns, newMergedPatterns,
+        EMPTY_ARRAY, YES_JAVA);
+    advancedPaths.testAdvancedJavaPathAnt(getAntFilter(newMergedPatterns,
+        EMPTY_ARRAY, 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) {
+      String excludes[], String skips[], boolean defaultExcludes,
+      final boolean isJava, String tag) {
final ZipScanner scanner = DefaultFilters.getScanner(includes, excludes,
-        defaultExcludes, true);
+        skips, defaultExcludes, true);
     return new ResourceFilterString(new ResourceFilter() {
       public boolean allows(String path) {
         if (isJava && !path.endsWith(".java")) {
@@ -441,19 +491,19 @@
   }

   private ResourceFilter getFilterWithCatchAll(String includesList[],
-      String excludesList[], boolean isJava) {
+      String excludesList[], String skipList[], boolean isJava) {
     if (isJava) {
return new DefaultFilters().customJavaFilter(includesList, excludesList,
-          true, true);
+          skipList, true, true);
     }
     return new DefaultFilters().customResourceFilter(includesList,
-        excludesList, true, true);
+        excludesList, skipList, true, true);
   }

   // caseSensitive and excludeDefaults are set
   private ResourceFilter getFilterWithoutCatchAll(String includesList[],
-      String excludesList[], boolean isJava) {
+      String excludesList[], String skipList[], boolean isJava) {
     return new DefaultFilters().customFilterWithCatchAll(includesList,
-        excludesList, true, null, isJava);
+        excludesList, skipList, true, null, isJava);
   }
 }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to