KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > Zip


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package org.apache.tools.ant.taskdefs;
19
20 import java.io.ByteArrayInputStream JavaDoc;
21 import java.io.ByteArrayOutputStream JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.OutputStream JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Enumeration JavaDoc;
30 import java.util.Hashtable JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.Stack JavaDoc;
33 import java.util.Vector JavaDoc;
34 import java.util.zip.CRC32 JavaDoc;
35
36 import org.apache.tools.ant.BuildException;
37 import org.apache.tools.ant.DirectoryScanner;
38 import org.apache.tools.ant.FileScanner;
39 import org.apache.tools.ant.Project;
40 import org.apache.tools.ant.types.ArchiveFileSet;
41 import org.apache.tools.ant.types.EnumeratedAttribute;
42 import org.apache.tools.ant.types.FileSet;
43 import org.apache.tools.ant.types.PatternSet;
44 import org.apache.tools.ant.types.Resource;
45 import org.apache.tools.ant.types.ResourceCollection;
46 import org.apache.tools.ant.types.ZipFileSet;
47 import org.apache.tools.ant.types.ZipScanner;
48 import org.apache.tools.ant.types.resources.ArchiveResource;
49 import org.apache.tools.ant.types.resources.FileResource;
50 import org.apache.tools.ant.util.FileNameMapper;
51 import org.apache.tools.ant.util.FileUtils;
52 import org.apache.tools.ant.util.GlobPatternMapper;
53 import org.apache.tools.ant.util.IdentityMapper;
54 import org.apache.tools.ant.util.MergingMapper;
55 import org.apache.tools.ant.util.ResourceUtils;
56 import org.apache.tools.zip.ZipEntry;
57 import org.apache.tools.zip.ZipExtraField;
58 import org.apache.tools.zip.ZipFile;
59 import org.apache.tools.zip.ZipOutputStream;
60
61 /**
62  * Create a Zip file.
63  *
64  * @since Ant 1.1
65  *
66  * @ant.task category="packaging"
67  */

68 public class Zip extends MatchingTask {
69     // CheckStyle:VisibilityModifier OFF - bc
70

71     protected File JavaDoc zipFile;
72     // use to scan own archive
73
private ZipScanner zs;
74     private File JavaDoc baseDir;
75     protected Hashtable JavaDoc entries = new Hashtable JavaDoc();
76     private Vector JavaDoc groupfilesets = new Vector JavaDoc();
77     private Vector JavaDoc filesetsFromGroupfilesets = new Vector JavaDoc();
78     protected String JavaDoc duplicate = "add";
79     private boolean doCompress = true;
80     private boolean doUpdate = false;
81     // shadow of the above if the value is altered in execute
82
private boolean savedDoUpdate = false;
83     private boolean doFilesonly = false;
84     protected String JavaDoc archiveType = "zip";
85
86     // For directories:
87
private static final long EMPTY_CRC = new CRC32 JavaDoc ().getValue ();
88     protected String JavaDoc emptyBehavior = "skip";
89     private Vector JavaDoc resources = new Vector JavaDoc();
90     protected Hashtable JavaDoc addedDirs = new Hashtable JavaDoc();
91     private Vector JavaDoc addedFiles = new Vector JavaDoc();
92
93     protected boolean doubleFilePass = false;
94     protected boolean skipWriting = false;
95
96     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
97
98     // CheckStyle:VisibilityModifier ON
99

100     /**
101      * true when we are adding new files into the Zip file, as opposed
102      * to adding back the unchanged files
103      */

104     private boolean addingNewFiles = false;
105
106     /**
107      * Encoding to use for filenames, defaults to the platform's
108      * default encoding.
109      */

110     private String JavaDoc encoding;
111
112     /**
113      * Whether the original compression of entries coming from a ZIP
114      * archive should be kept (for example when updating an archive).
115      *
116      * @since Ant 1.6
117      */

118     private boolean keepCompression = false;
119
120     /**
121      * Whether the file modification times will be rounded up to the
122      * next even number of seconds.
123      *
124      * @since Ant 1.6.2
125      */

126     private boolean roundUp = true;
127
128     /**
129      * Comment for the archive.
130      * @since Ant 1.6.3
131      */

132     private String JavaDoc comment = "";
133
134     private int level = ZipOutputStream.DEFAULT_COMPRESSION;
135
136     /**
137      * This is the name/location of where to
138      * create the .zip file.
139      * @param zipFile the path of the zipFile
140      * @deprecated since 1.5.x.
141      * Use setDestFile(File) instead.
142      * @ant.attribute ignore="true"
143      */

144     public void setZipfile(File JavaDoc zipFile) {
145         setDestFile(zipFile);
146     }
147
148     /**
149      * This is the name/location of where to
150      * create the file.
151      * @param file the path of the zipFile
152      * @since Ant 1.5
153      * @deprecated since 1.5.x.
154      * Use setDestFile(File) instead.
155      * @ant.attribute ignore="true"
156      */

157     public void setFile(File JavaDoc file) {
158         setDestFile(file);
159     }
160
161
162     /**
163      * The file to create; required.
164      * @since Ant 1.5
165      * @param destFile The new destination File
166      */

167     public void setDestFile(File JavaDoc destFile) {
168        this.zipFile = destFile;
169     }
170
171     /**
172      * The file to create.
173      * @return the destination file
174      * @since Ant 1.5.2
175      */

176     public File JavaDoc getDestFile() {
177         return zipFile;
178     }
179
180
181     /**
182      * Directory from which to archive files; optional.
183      * @param baseDir the base directory
184      */

185     public void setBasedir(File JavaDoc baseDir) {
186         this.baseDir = baseDir;
187     }
188
189     /**
190      * Whether we want to compress the files or only store them;
191      * optional, default=true;
192      * @param c if true, compress the files
193      */

194     public void setCompress(boolean c) {
195         doCompress = c;
196     }
197
198     /**
199      * Whether we want to compress the files or only store them;
200      * @return true if the files are to be compressed
201      * @since Ant 1.5.2
202      */

203     public boolean isCompress() {
204         return doCompress;
205     }
206
207     /**
208      * If true, emulate Sun's jar utility by not adding parent directories;
209      * optional, defaults to false.
210      * @param f if true, emulate sun's jar by not adding parent directories
211      */

212     public void setFilesonly(boolean f) {
213         doFilesonly = f;
214     }
215
216     /**
217      * If true, updates an existing file, otherwise overwrite
218      * any existing one; optional defaults to false.
219      * @param c if true, updates an existing zip file
220      */

221     public void setUpdate(boolean c) {
222         doUpdate = c;
223         savedDoUpdate = c;
224     }
225
226     /**
227      * Are we updating an existing archive?
228      * @return true if updating an existing archive
229      */

230     public boolean isInUpdateMode() {
231         return doUpdate;
232     }
233
234     /**
235      * Adds a set of files.
236      * @param set the fileset to add
237      */

238     public void addFileset(FileSet set) {
239         add(set);
240     }
241
242     /**
243      * Adds a set of files that can be
244      * read from an archive and be given a prefix/fullpath.
245      * @param set the zipfileset to add
246      */

247     public void addZipfileset(ZipFileSet set) {
248         add(set);
249     }
250
251     /**
252      * Add a collection of resources to be archived.
253      * @param a the resources to archive
254      * @since Ant 1.7
255      */

256     public void add(ResourceCollection a) {
257         resources.add(a);
258     }
259
260     /**
261      * Adds a group of zip files.
262      * @param set the group (a fileset) to add
263      */

264     public void addZipGroupFileset(FileSet set) {
265         groupfilesets.addElement(set);
266     }
267
268     /**
269      * Sets behavior for when a duplicate file is about to be added -
270      * one of <code>add</code>, <code>preserve</code> or <code>fail</code>.
271      * Possible values are: <code>add</code> (keep both
272      * of the files); <code>preserve</code> (keep the first version
273      * of the file found); <code>fail</code> halt a problem
274      * Default for zip tasks is <code>add</code>
275      * @param df a <code>Duplicate</code> enumerated value
276      */

277     public void setDuplicate(Duplicate df) {
278         duplicate = df.getValue();
279     }
280
281     /**
282      * Possible behaviors when there are no matching files for the task:
283      * "fail", "skip", or "create".
284      */

285     public static class WhenEmpty extends EnumeratedAttribute {
286         /**
287          * The string values for the enumerated value
288          * @return the values
289          */

290         public String JavaDoc[] getValues() {
291             return new String JavaDoc[] {"fail", "skip", "create"};
292         }
293     }
294
295     /**
296      * Sets behavior of the task when no files match.
297      * Possible values are: <code>fail</code> (throw an exception
298      * and halt the build); <code>skip</code> (do not create
299      * any archive, but issue a warning); <code>create</code>
300      * (make an archive with no entries).
301      * Default for zip tasks is <code>skip</code>;
302      * for jar tasks, <code>create</code>.
303      * @param we a <code>WhenEmpty</code> enumerated value
304      */

305     public void setWhenempty(WhenEmpty we) {
306         emptyBehavior = we.getValue();
307     }
308
309     /**
310      * Encoding to use for filenames, defaults to the platform's
311      * default encoding.
312      *
313      * <p>For a list of possible values see <a
314      * HREF="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.</p>
315      * @param encoding the encoding name
316      */

317     public void setEncoding(String JavaDoc encoding) {
318         this.encoding = encoding;
319     }
320
321     /**
322      * Encoding to use for filenames.
323      * @return the name of the encoding to use
324      * @since Ant 1.5.2
325      */

326     public String JavaDoc getEncoding() {
327         return encoding;
328     }
329
330     /**
331      * Whether the original compression of entries coming from a ZIP
332      * archive should be kept (for example when updating an archive).
333      * Default is false.
334      * @param keep if true, keep the original compression
335      * @since Ant 1.6
336      */

337     public void setKeepCompression(boolean keep) {
338         keepCompression = keep;
339     }
340
341     /**
342      * Comment to use for archive.
343      *
344      * @param comment The content of the comment.
345      * @since Ant 1.6.3
346      */

347     public void setComment(String JavaDoc comment) {
348         this.comment = comment;
349     }
350
351     /**
352      * Comment of the archive
353      *
354      * @return Comment of the archive.
355      * @since Ant 1.6.3
356      */

357     public String JavaDoc getComment() {
358         return comment;
359     }
360
361     /**
362      * Set the compression level to use. Default is
363      * ZipOutputStream.DEFAULT_COMPRESSION.
364      * @param level compression level.
365      * @since Ant 1.7
366      */

367     public void setLevel(int level) {
368         this.level = level;
369     }
370
371     /**
372      * Get the compression level.
373      * @return compression level.
374      * @since Ant 1.7
375      */

376     public int getLevel() {
377         return level;
378     }
379
380     /**
381      * Whether the file modification times will be rounded up to the
382      * next even number of seconds.
383      *
384      * <p>Zip archives store file modification times with a
385      * granularity of two seconds, so the times will either be rounded
386      * up or down. If you round down, the archive will always seem
387      * out-of-date when you rerun the task, so the default is to round
388      * up. Rounding up may lead to a different type of problems like
389      * JSPs inside a web archive that seem to be slightly more recent
390      * than precompiled pages, rendering precompilation useless.</p>
391      * @param r a <code>boolean</code> value
392      * @since Ant 1.6.2
393      */

394     public void setRoundUp(boolean r) {
395         roundUp = r;
396     }
397
398     /**
399      * validate and build
400      * @throws BuildException on error
401      */

402     public void execute() throws BuildException {
403
404         if (doubleFilePass) {
405             skipWriting = true;
406             executeMain();
407             skipWriting = false;
408             executeMain();
409         } else {
410             executeMain();
411         }
412     }
413
414     /**
415      * Build the zip file.
416      * This is called twice if doubleFilePass is true.
417      * @throws BuildException on error
418      */

419     public void executeMain() throws BuildException {
420
421         if (baseDir == null && resources.size() == 0
422             && groupfilesets.size() == 0 && "zip".equals(archiveType)) {
423             throw new BuildException("basedir attribute must be set, "
424                                      + "or at least one "
425                                      + "resource collection must be given!");
426         }
427
428         if (zipFile == null) {
429             throw new BuildException("You must specify the "
430                                      + archiveType + " file to create!");
431         }
432
433         if (zipFile.exists() && !zipFile.isFile()) {
434             throw new BuildException(zipFile + " is not a file.");
435         }
436
437         if (zipFile.exists() && !zipFile.canWrite()) {
438             throw new BuildException(zipFile + " is read-only.");
439         }
440
441         // Renamed version of original file, if it exists
442
File JavaDoc renamedFile = null;
443         addingNewFiles = true;
444
445         // Whether or not an actual update is required -
446
// we don't need to update if the original file doesn't exist
447
if (doUpdate && !zipFile.exists()) {
448             doUpdate = false;
449             log("ignoring update attribute as " + archiveType
450                 + " doesn't exist.", Project.MSG_DEBUG);
451         }
452
453         // Add the files found in groupfileset to fileset
454
for (int i = 0; i < groupfilesets.size(); i++) {
455
456             log("Processing groupfileset ", Project.MSG_VERBOSE);
457             FileSet fs = (FileSet) groupfilesets.elementAt(i);
458             FileScanner scanner = fs.getDirectoryScanner(getProject());
459             String JavaDoc[] files = scanner.getIncludedFiles();
460             File JavaDoc basedir = scanner.getBasedir();
461             for (int j = 0; j < files.length; j++) {
462
463                 log("Adding file " + files[j] + " to fileset",
464                     Project.MSG_VERBOSE);
465                 ZipFileSet zf = new ZipFileSet();
466                 zf.setProject(getProject());
467                 zf.setSrc(new File JavaDoc(basedir, files[j]));
468                 add(zf);
469                 filesetsFromGroupfilesets.addElement(zf);
470             }
471         }
472
473         // collect filesets to pass them to getResourcesToAdd
474
Vector JavaDoc vfss = new Vector JavaDoc();
475         if (baseDir != null) {
476             FileSet fs = (FileSet) getImplicitFileSet().clone();
477             fs.setDir(baseDir);
478             vfss.addElement(fs);
479         }
480         for (int i = 0; i < resources.size(); i++) {
481             ResourceCollection rc = (ResourceCollection) resources.elementAt(i);
482             vfss.addElement(rc);
483         }
484
485         ResourceCollection[] fss = new ResourceCollection[vfss.size()];
486         vfss.copyInto(fss);
487         boolean success = false;
488         try {
489             // can also handle empty archives
490
ArchiveState state = getResourcesToAdd(fss, zipFile, false);
491
492             // quick exit if the target is up to date
493
if (!state.isOutOfDate()) {
494                 return;
495             }
496
497             if (!zipFile.exists() && state.isWithoutAnyResources()) {
498                 createEmptyZip(zipFile);
499                 return;
500             }
501             Resource[][] addThem = state.getResourcesToAdd();
502
503             if (doUpdate) {
504                 renamedFile =
505                     FILE_UTILS.createTempFile("zip", ".tmp",
506                                               zipFile.getParentFile());
507                 renamedFile.deleteOnExit();
508
509                 try {
510                     FILE_UTILS.rename(zipFile, renamedFile);
511                 } catch (SecurityException JavaDoc e) {
512                     throw new BuildException(
513                         "Not allowed to rename old file ("
514                         + zipFile.getAbsolutePath()
515                         + ") to temporary file");
516                 } catch (IOException JavaDoc e) {
517                     throw new BuildException(
518                         "Unable to rename old file ("
519                         + zipFile.getAbsolutePath()
520                         + ") to temporary file");
521                 }
522             }
523
524             String JavaDoc action = doUpdate ? "Updating " : "Building ";
525
526             log(action + archiveType + ": " + zipFile.getAbsolutePath());
527
528             ZipOutputStream zOut = null;
529             try {
530                 if (!skipWriting) {
531                     zOut = new ZipOutputStream(zipFile);
532
533                     zOut.setEncoding(encoding);
534                     zOut.setMethod(doCompress
535                         ? ZipOutputStream.DEFLATED : ZipOutputStream.STORED);
536                     zOut.setLevel(level);
537                 }
538                 initZipOutputStream(zOut);
539
540                 // Add the explicit resource collections to the archive.
541
for (int i = 0; i < fss.length; i++) {
542                     if (addThem[i].length != 0) {
543                         addResources(fss[i], addThem[i], zOut);
544                     }
545                 }
546
547                 if (doUpdate) {
548                     addingNewFiles = false;
549                     ZipFileSet oldFiles = new ZipFileSet();
550                     oldFiles.setProject(getProject());
551                     oldFiles.setSrc(renamedFile);
552                     oldFiles.setDefaultexcludes(false);
553
554                     for (int i = 0; i < addedFiles.size(); i++) {
555                         PatternSet.NameEntry ne = oldFiles.createExclude();
556                         ne.setName((String JavaDoc) addedFiles.elementAt(i));
557                     }
558                     DirectoryScanner ds =
559                         oldFiles.getDirectoryScanner(getProject());
560                     ((ZipScanner) ds).setEncoding(encoding);
561
562                     String JavaDoc[] f = ds.getIncludedFiles();
563                     Resource[] r = new Resource[f.length];
564                     for (int i = 0; i < f.length; i++) {
565                         r[i] = ds.getResource(f[i]);
566                     }
567
568                     if (!doFilesonly) {
569                         String JavaDoc[] d = ds.getIncludedDirectories();
570                         Resource[] dr = new Resource[d.length];
571                         for (int i = 0; i < d.length; i++) {
572                             dr[i] = ds.getResource(d[i]);
573                         }
574                         Resource[] tmp = r;
575                         r = new Resource[tmp.length + dr.length];
576                         System.arraycopy(dr, 0, r, 0, dr.length);
577                         System.arraycopy(tmp, 0, r, dr.length, tmp.length);
578                     }
579                     addResources(oldFiles, r, zOut);
580                 }
581                 if (zOut != null) {
582                     zOut.setComment(comment);
583                 }
584                 finalizeZipOutputStream(zOut);
585
586                 // If we've been successful on an update, delete the
587
// temporary file
588
if (doUpdate) {
589                     if (!renamedFile.delete()) {
590                         log ("Warning: unable to delete temporary file "
591                             + renamedFile.getName(), Project.MSG_WARN);
592                     }
593                 }
594                 success = true;
595             } finally {
596                 // Close the output stream.
597
try {
598                     if (zOut != null) {
599                         zOut.close();
600                     }
601                 } catch (IOException JavaDoc ex) {
602                     // If we're in this finally clause because of an
603
// exception, we don't really care if there's an
604
// exception when closing the stream. E.g. if it
605
// throws "ZIP file must have at least one entry",
606
// because an exception happened before we added
607
// any files, then we must swallow this
608
// exception. Otherwise, the error that's reported
609
// will be the close() error, which is not the
610
// real cause of the problem.
611
if (success) {
612                         throw ex;
613                     }
614                 }
615             }
616         } catch (IOException JavaDoc ioe) {
617             String JavaDoc msg = "Problem creating " + archiveType + ": "
618                 + ioe.getMessage();
619
620             // delete a bogus ZIP file (but only if it's not the original one)
621
if ((!doUpdate || renamedFile != null) && !zipFile.delete()) {
622                 msg += " (and the archive is probably corrupt but I could not "
623                     + "delete it)";
624             }
625
626             if (doUpdate && renamedFile != null) {
627                 try {
628                     FILE_UTILS.rename(renamedFile, zipFile);
629                 } catch (IOException JavaDoc e) {
630                     msg += " (and I couldn't rename the temporary file "
631                             + renamedFile.getName() + " back)";
632                 }
633             }
634
635             throw new BuildException(msg, ioe, getLocation());
636         } finally {
637             cleanUp();
638         }
639     }
640
641     /**
642      * Indicates if the task is adding new files into the archive as opposed to
643      * copying back unchanged files from the backup copy
644      * @return true if adding new files
645      */

646     protected final boolean isAddingNewFiles() {
647         return addingNewFiles;
648     }
649
650     /**
651      * Add the given resources.
652      *
653      * @param fileset may give additional information like fullpath or
654      * permissions.
655      * @param resources the resources to add
656      * @param zOut the stream to write to
657      * @throws IOException on error
658      *
659      * @since Ant 1.5.2
660      */

661     protected final void addResources(FileSet fileset, Resource[] resources,
662                                       ZipOutputStream zOut)
663         throws IOException JavaDoc {
664
665         String JavaDoc prefix = "";
666         String JavaDoc fullpath = "";
667         int dirMode = ArchiveFileSet.DEFAULT_DIR_MODE;
668         int fileMode = ArchiveFileSet.DEFAULT_FILE_MODE;
669
670         ArchiveFileSet zfs = null;
671         if (fileset instanceof ArchiveFileSet) {
672             zfs = (ArchiveFileSet) fileset;
673             prefix = zfs.getPrefix(getProject());
674             fullpath = zfs.getFullpath(getProject());
675             dirMode = zfs.getDirMode(getProject());
676             fileMode = zfs.getFileMode(getProject());
677         }
678
679         if (prefix.length() > 0 && fullpath.length() > 0) {
680             throw new BuildException("Both prefix and fullpath attributes must"
681                                      + " not be set on the same fileset.");
682         }
683
684         if (resources.length != 1 && fullpath.length() > 0) {
685             throw new BuildException("fullpath attribute may only be specified"
686                                      + " for filesets that specify a single"
687                                      + " file.");
688         }
689
690         if (prefix.length() > 0) {
691             if (!prefix.endsWith("/") && !prefix.endsWith("\\")) {
692                 prefix += "/";
693             }
694             addParentDirs(null, prefix, zOut, "", dirMode);
695         }
696
697         ZipFile zf = null;
698         try {
699             boolean dealingWithFiles = false;
700             File JavaDoc base = null;
701
702             if (zfs == null || zfs.getSrc(getProject()) == null) {
703                 dealingWithFiles = true;
704                 base = fileset.getDir(getProject());
705             } else if (zfs instanceof ZipFileSet) {
706                 zf = new ZipFile(zfs.getSrc(getProject()), encoding);
707             }
708
709             for (int i = 0; i < resources.length; i++) {
710                 String JavaDoc name = null;
711                 if (fullpath.length() > 0) {
712                     name = fullpath;
713                 } else {
714                     name = resources[i].getName();
715                 }
716                 name = name.replace(File.separatorChar, '/');
717
718                 if ("".equals(name)) {
719                     continue;
720                 }
721                 if (resources[i].isDirectory() && !name.endsWith("/")) {
722                     name = name + "/";
723                 }
724
725                 if (!doFilesonly && !dealingWithFiles
726                     && resources[i].isDirectory()
727                     && !zfs.hasDirModeBeenSet()) {
728                     int nextToLastSlash = name.lastIndexOf("/",
729                                                            name.length() - 2);
730                     if (nextToLastSlash != -1) {
731                         addParentDirs(base, name.substring(0,
732                                                            nextToLastSlash + 1),
733                                       zOut, prefix, dirMode);
734                     }
735                     if (zf != null) {
736                         ZipEntry ze = zf.getEntry(resources[i].getName());
737                         addParentDirs(base, name, zOut, prefix,
738                                       ze.getUnixMode());
739                     } else {
740                         ArchiveResource tr = (ArchiveResource) resources[i];
741                         addParentDirs(base, name, zOut, prefix,
742                                       tr.getMode());
743                     }
744
745                 } else {
746                     addParentDirs(base, name, zOut, prefix, dirMode);
747                 }
748
749                 if (!resources[i].isDirectory() && dealingWithFiles) {
750                     File JavaDoc f = FILE_UTILS.resolveFile(base,
751                                                    resources[i].getName());
752                     zipFile(f, zOut, prefix + name, fileMode);
753                 } else if (!resources[i].isDirectory()) {
754                     if (zf != null) {
755                     ZipEntry ze = zf.getEntry(resources[i].getName());
756
757                     if (ze != null) {
758                         boolean oldCompress = doCompress;
759                         if (keepCompression) {
760                             doCompress = (ze.getMethod() == ZipEntry.DEFLATED);
761                         }
762                         try {
763                             zipFile(zf.getInputStream(ze), zOut, prefix + name,
764                                     ze.getTime(), zfs.getSrc(getProject()),
765                                     zfs.hasFileModeBeenSet() ? fileMode
766                                     : ze.getUnixMode());
767                         } finally {
768                             doCompress = oldCompress;
769                         }
770                     }
771                     } else {
772                         ArchiveResource tr = (ArchiveResource) resources[i];
773                         InputStream JavaDoc is = null;
774                         try {
775                             is = tr.getInputStream();
776                             zipFile(is, zOut, prefix + name,
777                                     resources[i].getLastModified(),
778                                     zfs.getSrc(getProject()),
779                                     zfs.hasFileModeBeenSet() ? fileMode
780                                     : tr.getMode());
781                         } finally {
782