diff --git a/src/main/org/apache/tools/ant/taskdefs/Zip.java b/src/main/org/apache/tools/ant/taskdefs/Zip.java
index 348c581f1..c05303f21 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Zip.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Zip.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
@@ -52,7 +53,9 @@ import org.apache.tools.ant.types.ZipScanner;
import org.apache.tools.ant.types.resources.ArchiveResource;
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.types.resources.ZipResource;
+import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.GlobPatternMapper;
@@ -99,6 +102,21 @@ public class Zip extends MatchingTask {
protected Hashtable addedDirs = new Hashtable();
private Vector addedFiles = new Vector();
+ private static final ResourceSelector MISSING_SELECTOR =
+ new ResourceSelector() {
+ public boolean isSelected(Resource target) {
+ return !target.isExists();
+ }
+ };
+
+ private static final ResourceUtils.ResourceSelectorProvider
+ MISSING_DIR_PROVIDER = new ResourceUtils.ResourceSelectorProvider() {
+ public ResourceSelector
+ getTargetSelectorForSource(Resource sr) {
+ return MISSING_SELECTOR;
+ }
+ };
+
/**
* If this flag is true, execute() will run most operations twice,
* the first time with {@link #skipWriting skipWriting} set to
@@ -1353,15 +1371,29 @@ public class Zip extends MatchingTask {
}
}
- Resource[] resources = initialResources[i];
- if (doFilesonly) {
- resources = selectFileResources(resources);
- }
+ Resource[] resources = selectFileResources(initialResources[i]);
newerResources[i] =
ResourceUtils.selectOutOfDateSources(this,
resources,
myMapper,
getZipScanner());
+ if (!doFilesonly) {
+ Union u = new Union();
+ u.addAll(Arrays
+ .asList(selectDirectoryResources(initialResources[i])));
+ ResourceCollection rc =
+ ResourceUtils.selectSources(this, u,
+ myMapper,
+ getZipScanner(),
+ MISSING_DIR_PROVIDER);
+ if (rc.size() > 0) {
+ ArrayList newer = new ArrayList();
+ newer.addAll(Arrays.asList(((Union) rc).listResources()));
+ newer.addAll(Arrays.asList(newerResources[i]));
+ newerResources[i] =
+ (Resource[]) newer.toArray(newerResources[i]);
+ }
+ }
needsUpdate = needsUpdate || (newerResources[i].length > 0);
if (needsUpdate && !doUpdate) {
@@ -1445,15 +1477,29 @@ public class Zip extends MatchingTask {
}
}
- Resource[] rs = initialResources[i];
- if (doFilesonly) {
- rs = selectFileResources(rs);
- }
+ Resource[] rs = selectFileResources(initialResources[i]);
newerResources[i] =
ResourceUtils.selectOutOfDateSources(this,
rs,
new IdentityMapper(),
getZipScanner());
+ if (!doFilesonly) {
+ Union u = new Union();
+ u.addAll(Arrays
+ .asList(selectDirectoryResources(initialResources[i])));
+ ResourceCollection rc =
+ ResourceUtils.selectSources(this, u,
+ new IdentityMapper(),
+ getZipScanner(),
+ MISSING_DIR_PROVIDER);
+ if (rc.size() > 0) {
+ ArrayList newer = new ArrayList();
+ newer.addAll(Arrays.asList(((Union) rc).listResources()));
+ newer.addAll(Arrays.asList(newerResources[i]));
+ newerResources[i] =
+ (Resource[]) newer.toArray(newerResources[i]);
+ }
+ }
needsUpdate = needsUpdate || (newerResources[i].length > 0);
if (needsUpdate && !doUpdate) {
@@ -1912,25 +1958,60 @@ public class Zip extends MatchingTask {
* @since Ant 1.6
*/
protected Resource[] selectFileResources(Resource[] orig) {
+ return selectResources(orig,
+ new ResourceSelector() {
+ public boolean isSelected(Resource r) {
+ if (!r.isDirectory()) {
+ return true;
+ } else if (doFilesonly) {
+ logOnFirstPass("Ignoring directory "
+ + r.getName()
+ + " as only files will"
+ + " be added.",
+ Project.MSG_VERBOSE);
+ }
+ return false;
+ }
+ });
+ }
+
+ /**
+ * Drops all non-directory resources from the given array.
+ * @param orig the resources to filter
+ * @return the filters resources
+ * @since Ant 1.8.0
+ */
+ protected Resource[] selectDirectoryResources(Resource[] orig) {
+ return selectResources(orig,
+ new ResourceSelector() {
+ public boolean isSelected(Resource r) {
+ return r.isDirectory();
+ }
+ });
+ }
+
+ /**
+ * Drops all resources from the given array that are not selected
+ * @param orig the resources to filter
+ * @return the filters resources
+ * @since Ant 1.8.0
+ */
+ protected Resource[] selectResources(Resource[] orig,
+ ResourceSelector selector) {
if (orig.length == 0) {
return orig;
}
- Vector v = new Vector(orig.length);
+ ArrayList v = new ArrayList(orig.length);
for (int i = 0; i < orig.length; i++) {
- if (!orig[i].isDirectory()) {
- v.addElement(orig[i]);
- } else {
- logOnFirstPass("Ignoring directory " + orig[i].getName()
- + " as only files will be added.",
- Project.MSG_VERBOSE);
+ if (selector.isSelected(orig[i])) {
+ v.add(orig[i]);
}
}
if (v.size() != orig.length) {
Resource[] r = new Resource[v.size()];
- v.copyInto(r);
- return r;
+ return (Resource[]) v.toArray(r);
}
return orig;
}
diff --git a/src/main/org/apache/tools/ant/util/ResourceUtils.java b/src/main/org/apache/tools/ant/util/ResourceUtils.java
index 8d5d1583d..7f821a2f6 100644
--- a/src/main/org/apache/tools/ant/util/ResourceUtils.java
+++ b/src/main/org/apache/tools/ant/util/ResourceUtils.java
@@ -130,12 +130,51 @@ public class ResourceUtils {
FileNameMapper mapper,
ResourceFactory targets,
final long granularity) {
+ logFuture(logTo, source, granularity);
+ ResourceSelectorProvider p =
+ new ResourceSelectorProvider() {
+ public ResourceSelector
+ getTargetSelectorForSource(final Resource sr) {
+ return new ResourceSelector() {
+ public boolean isSelected(Resource target) {
+ /* Extra I/O, probably wasted:
+ if (target.isDirectory()) {
+ return false;
+ }
+ */
+ return SelectorUtils.isOutOfDate(sr, target,
+ granularity);
+ }
+ };
+ }
+ };
+ return selectSources(logTo, source, mapper, targets, p);
+ }
+
+ /**
+ * Tells which sources should be reprocessed because the given
+ * selector selects at least one target.
+ *
+ * @param logTo where to send (more or less) interesting output.
+ * @param source ResourceCollection.
+ * @param mapper filename mapper indicating how to find the target Resources.
+ * @param targets object able to map a relative path as a Resource.
+ * @param selector returns a selector that is applied to target
+ * files. If it selects at least one target the source will be
+ * added to the returned collection.
+ * @return ResourceCollection.
+ * @since Ant 1.8.0
+ */
+ public static ResourceCollection selectSources(ProjectComponent logTo,
+ ResourceCollection source,
+ FileNameMapper mapper,
+ ResourceFactory targets,
+ ResourceSelectorProvider selector) {
if (source.size() == 0) {
logTo.log("No sources found.", Project.MSG_VERBOSE);
return Resources.NONE;
}
source = Union.getInstance(source);
- logFuture(logTo, source, granularity);
Union result = new Union();
for (Iterator iter = source.iterator(); iter.hasNext();) {
@@ -168,16 +207,7 @@ public class ResourceUtils {
}
//find the out-of-date targets:
Restrict r = new Restrict();
- r.add(new ResourceSelector() {
- public boolean isSelected(Resource target) {
- /* Extra I/O, probably wasted:
- if (target.isDirectory()) {
- return false;
- }
- */
- return SelectorUtils.isOutOfDate(sr, target, granularity);
- }
- });
+ r.add(selector.getTargetSelectorForSource(sr));
r.add(targetColl);
if (r.size() > 0) {
result.add(sr);
@@ -639,4 +669,8 @@ public class ResourceUtils {
}
return resource.getOutputStream();
}
+
+ public static interface ResourceSelectorProvider {
+ ResourceSelector getTargetSelectorForSource(Resource source);
+ }
}
diff --git a/src/tests/antunit/taskdefs/zip-test.xml b/src/tests/antunit/taskdefs/zip-test.xml
index 7edcaf640..6f0d77c0e 100644
--- a/src/tests/antunit/taskdefs/zip-test.xml
+++ b/src/tests/antunit/taskdefs/zip-test.xml
@@ -86,9 +86,8 @@
-
-