This patch improves the robustness and error reporting of these tasks especially when no files are to be included in the archives. Submitted by: Jesse Glick <Jesse.Glick@netbeans.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267947 13f79535-47bb-0310-9956-ffa450edef68master
@@ -90,7 +90,6 @@ | |||||
</javac> | </javac> | ||||
<copydir src="${src.dir}" dest="${build.classes}"> | <copydir src="${src.dir}" dest="${build.classes}"> | ||||
<include name="**/defaultManifest.mf" /> | |||||
<include name="**/*.properties" /> | <include name="**/*.properties" /> | ||||
</copydir> | </copydir> | ||||
@@ -102,6 +101,7 @@ | |||||
forceoverwrite="true" | forceoverwrite="true" | ||||
filtering="on"> | filtering="on"> | ||||
<include name="**/version.txt" /> | <include name="**/version.txt" /> | ||||
<include name="**/defaultManifest.mf" /> | |||||
</copydir> | </copydir> | ||||
</target> | </target> | ||||
@@ -2022,6 +2022,15 @@ supports all attributes of <code><fileset></code> | |||||
<code><include></code>, <code><exclude></code>, | <code><include></code>, <code><exclude></code>, | ||||
<code><patternset></code> and <code><patternsetref></code> | <code><patternset></code> and <code><patternsetref></code> | ||||
elements.</p> | elements.</p> | ||||
<p>You can also use nested file sets for more flexibility, and specify | |||||
multiple ones to merge together different trees of files into one JAR. | |||||
See the <a href="#zip">Zip</a> task for more details and examples.</p> | |||||
<p>If the manifest is omitted, a simple one will be supplied by Ant. | |||||
You should not include <samp>META-INF/MANIFEST.MF</samp> in your set of files. | |||||
<p>The <code>whenempty</code> parameter controls what happens when no files match. | |||||
If <code>create</code> (the default), the JAR is created anyway with only a manifest. | |||||
If <code>skip</code>, the JAR is not created and a warning is issued. | |||||
If <code>fail</code>, the JAR is not created and the build is halted with an error. | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -2037,7 +2046,7 @@ elements.</p> | |||||
<tr> | <tr> | ||||
<td valign="top">basedir</td> | <td valign="top">basedir</td> | ||||
<td valign="top">the directory from which to jar the files.</td> | <td valign="top">the directory from which to jar the files.</td> | ||||
<td valign="top" align="center">Yes</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">compress</td> | <td valign="top">compress</td> | ||||
@@ -2079,6 +2088,11 @@ elements.</p> | |||||
<td valign="top">the manifest file to use.</td> | <td valign="top">the manifest file to use.</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">whenempty</td> | |||||
<td valign="top">Behavior to use if no files match.</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<pre> <jar jarfile="${dist}/lib/app.jar" basedir="${build}/classes" /></pre> | <pre> <jar jarfile="${dist}/lib/app.jar" basedir="${build}/classes" /></pre> | ||||
@@ -2100,6 +2114,21 @@ with the name <code>Test.class</code> are excluded.</p> | |||||
called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Only | called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Only | ||||
files under the directory <code>mypackage/test</code> are used, and files with | files under the directory <code>mypackage/test</code> are used, and files with | ||||
the name <code>Test.class</code> are excluded.</p> | the name <code>Test.class</code> are excluded.</p> | ||||
<pre> <jar jarfile="${dist}/lib/app.jar"> | |||||
<fileset dir="${build}/classes" | |||||
excludes="**/Test.class" | |||||
/> | |||||
<fileset dir="${src}/resources"/> | |||||
</jar></pre> | |||||
<p>jars all files in the <code>${build}/classes</code> directory and also | |||||
in the <code>${src}/resources</code> directory together in a file | |||||
called <code>app.jar</code> in the <code>${dist}/lib</code> directory. | |||||
Files with the name <code>Test.class</code> are excluded. | |||||
If there are files such as <code>${build}/classes/mypackage/MyClass.class</code> | |||||
and <code>${src}/resources/mypackage/image.gif</code>, they will appear | |||||
in the same directory in the JAR (and thus be considered in the same package | |||||
by Java).</p> | |||||
<hr> | <hr> | ||||
<h2><a name="java">Java</a></h2> | <h2><a name="java">Java</a></h2> | ||||
<h3>Description</h3> | <h3>Description</h3> | ||||
@@ -3655,6 +3684,19 @@ supports all attributes of <code><fileset></code> | |||||
<code><include></code>, <code><exclude></code>, | <code><include></code>, <code><exclude></code>, | ||||
<code><patternset></code> and <code><patternsetref></code> | <code><patternset></code> and <code><patternsetref></code> | ||||
elements.</p> | elements.</p> | ||||
<p>Or, you may place within it nested file sets, or references to file sets. | |||||
In this case <code>basedir</code> is optional; the implicit file set is <em>only used</em> | |||||
if <code>basedir</code> is set. You may use any mixture of the implicit file set | |||||
(with <code>basedir</code> set, and optional attributes like <code>includes</code> | |||||
and optional subelements like <code><include></code>); explicit nested | |||||
<code><fileset></code> elements; and nested <code><filesetref></code> | |||||
elements; so long as at least one fileset total is specified. The ZIP file will | |||||
only reflect the relative paths of files <em>within</em> each fileset.</p> | |||||
<p>The <code>whenempty</code> parameter controls what happens when no files match. | |||||
If <code>skip</code> (the default), the ZIP is not created and a warning is issued. | |||||
If <code>fail</code>, the ZIP is not created and the build is halted with an error. | |||||
If <code>create</code>, an empty ZIP file (explicitly zero entries) is created, | |||||
which should be recognized as such by compliant ZIP manipulation tools.</p> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -3670,7 +3712,7 @@ elements.</p> | |||||
<tr> | <tr> | ||||
<td valign="top">basedir</td> | <td valign="top">basedir</td> | ||||
<td valign="top">the directory from which to zip the files.</td> | <td valign="top">the directory from which to zip the files.</td> | ||||
<td align="center" valign="top">Yes</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">compress</td> | <td valign="top">compress</td> | ||||
@@ -3707,6 +3749,11 @@ elements.</p> | |||||
("yes"/"no"). Default excludes are used when omitted.</td> | ("yes"/"no"). Default excludes are used when omitted.</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">whenempty</td> | |||||
<td valign="top">Behavior when no files match.</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<pre> <zip zipfile="${dist}/manual.zip" | <pre> <zip zipfile="${dist}/manual.zip" | ||||
@@ -3729,6 +3776,14 @@ or files with the name <code>todo.html</code> are excluded.</p> | |||||
<p>zips all files in the <code>htdocs/manual</code> directory in a file called <code>manual.zip</code> | <p>zips all files in the <code>htdocs/manual</code> directory in a file called <code>manual.zip</code> | ||||
in the <code>${dist}</code> directory. Only html files under the directory <code>api</code> | in the <code>${dist}</code> directory. Only html files under the directory <code>api</code> | ||||
are zipped, and files with the name <code>todo.html</code> are excluded.</p> | are zipped, and files with the name <code>todo.html</code> are excluded.</p> | ||||
<pre> <zip zipfile="${dist}/manual.zip"> | |||||
<fileset dir="htdocs/manual"/> | |||||
<fileset dir="." includes="ChangeLog.txt"/> | |||||
</zip></pre> | |||||
<p>zips all files in the <code>htdocs/manual</code> directory in a file called <code>manual.zip</code> | |||||
in the <code>${dist}</code> directory, and also adds the file <code>ChangeLog.txt</code> in the | |||||
current directory. <code>ChangeLog.txt</code> will be added to the top of the ZIP file, just as if | |||||
it had been located at <code>htdocs/manual/ChangeLog.txt</code>.</p> | |||||
<hr> | <hr> | ||||
<h2><a name="optionaltasks">Optional tasks</a></h2> | <h2><a name="optionaltasks">Optional tasks</a></h2> | ||||
@@ -1 +1,3 @@ | |||||
Manifest-Version: 1.0 | Manifest-Version: 1.0 | ||||
Created-By: Ant @VERSION@ | |||||
@@ -86,38 +86,67 @@ public class Jar extends Zip { | |||||
super.zipDir(new File(manifest.getParent()), zOut, "META-INF/"); | super.zipDir(new File(manifest.getParent()), zOut, "META-INF/"); | ||||
super.zipFile(manifest, zOut, "META-INF/MANIFEST.MF"); | super.zipFile(manifest, zOut, "META-INF/MANIFEST.MF"); | ||||
} else { | } else { | ||||
/* | |||||
* We don't store directories at all and this one will cause a lot | |||||
* of problems with STORED Zip-Mode. | |||||
* | |||||
* That's why i've removed it -- Stefan Bodewig | |||||
*/ | |||||
// ZipEntry ze = new ZipEntry("META-INF/"); | |||||
// zOut.putNextEntry(ze); | |||||
String s = "/org/apache/tools/ant/defaultManifest.mf"; | String s = "/org/apache/tools/ant/defaultManifest.mf"; | ||||
InputStream in = this.getClass().getResourceAsStream(s); | InputStream in = this.getClass().getResourceAsStream(s); | ||||
if ( in == null ) | if ( in == null ) | ||||
throw new BuildException ( "Could not find: " + s ); | throw new BuildException ( "Could not find: " + s ); | ||||
super.zipDir(null, zOut, "META-INF/"); | |||||
zipFile(in, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis()); | zipFile(in, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis()); | ||||
} | } | ||||
} | } | ||||
protected boolean isUpToDate(FileScanner[] scanners, File zipFile) | |||||
{ | |||||
File[] files = grabFiles(scanners); | |||||
if (emptyBehavior == null) emptyBehavior = "create"; | |||||
if (files.length == 0) { | |||||
if (emptyBehavior.equals("skip")) { | |||||
log("Warning: skipping JAR archive " + zipFile + | |||||
" because no files were included.", Project.MSG_WARN); | |||||
return true; | |||||
} else if (emptyBehavior.equals("fail")) { | |||||
throw new BuildException("Cannot create JAR archive " + zipFile + | |||||
": no files were included.", location); | |||||
} else { | |||||
// create | |||||
if (!zipFile.exists() || | |||||
(manifest != null && | |||||
manifest.lastModified() > zipFile.lastModified())) | |||||
log("Note: creating empty JAR archive " + zipFile, Project.MSG_INFO); | |||||
// and continue below... | |||||
} | |||||
} | |||||
if (!zipFile.exists()) return false; | |||||
if (manifest != null && manifest.lastModified() > zipFile.lastModified()) | |||||
return false; | |||||
for (int i=0; i<files.length; i++) { | |||||
if (files[i].lastModified() > zipFile.lastModified()) { | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
protected void zipDir(File dir, ZipOutputStream zOut, String vPath) | protected void zipDir(File dir, ZipOutputStream zOut, String vPath) | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
// First add directory to zip entry | // First add directory to zip entry | ||||
if(!vPath.equals("META-INF/")) { | |||||
if(!vPath.equalsIgnoreCase("META-INF/")) { | |||||
// we already added a META-INF | // we already added a META-INF | ||||
super.zipDir(dir, zOut, vPath); | super.zipDir(dir, zOut, vPath); | ||||
} | } | ||||
// no warning if not, it is harmless in and of itself | |||||
} | } | ||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath) | protected void zipFile(File file, ZipOutputStream zOut, String vPath) | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
// We already added a META-INF/MANIFEST.MF | // We already added a META-INF/MANIFEST.MF | ||||
if (!vPath.equals("META-INF/MANIFEST.MF")) { | |||||
if (!vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) { | |||||
super.zipFile(file, zOut, vPath); | super.zipFile(file, zOut, vPath); | ||||
} else { | |||||
log("Warning: selected JAR files include a META-INF/MANIFEST.MF which will be ignored " + | |||||
"(please use manifest attribute to jar task)", Project.MSG_WARN); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -55,9 +55,11 @@ | |||||
package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
import org.apache.tools.ant.*; | import org.apache.tools.ant.*; | ||||
import org.apache.tools.ant.types.*; | |||||
import java.io.*; | import java.io.*; | ||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import java.util.Hashtable; | |||||
import java.util.StringTokenizer; | import java.util.StringTokenizer; | ||||
import java.util.Vector; | import java.util.Vector; | ||||
import java.util.zip.*; | import java.util.zip.*; | ||||
@@ -75,6 +77,10 @@ public class Zip extends MatchingTask { | |||||
private File baseDir; | private File baseDir; | ||||
private boolean doCompress = true; | private boolean doCompress = true; | ||||
protected String archiveType = "zip"; | protected String archiveType = "zip"; | ||||
// For directories: | |||||
private static long emptyCrc = new CRC32 ().getValue (); | |||||
protected String emptyBehavior = null; | |||||
private Vector filesets = new Vector (); | |||||
/** | /** | ||||
* This is the name/location of where to | * This is the name/location of where to | ||||
@@ -99,73 +105,113 @@ public class Zip extends MatchingTask { | |||||
doCompress = Project.toBoolean(compress); | doCompress = Project.toBoolean(compress); | ||||
} | } | ||||
public void execute() throws BuildException { | |||||
if (baseDir == null) { | |||||
throw new BuildException("basedir attribute must be set!"); | |||||
} | |||||
if (!baseDir.exists()) { | |||||
throw new BuildException("basedir does not exist!"); | |||||
} | |||||
/** | |||||
* Adds a set of files (nested fileset attribute). | |||||
*/ | |||||
public void addFileset(FileSet set) { | |||||
filesets.addElement(set); | |||||
} | |||||
/** | |||||
* Adds a reference to a set of files (nested filesetref element). | |||||
*/ | |||||
public void addFilesetref(Reference ref) { | |||||
filesets.addElement(ref); | |||||
} | |||||
/** | |||||
* Sets behavior of the task when no files match. | |||||
* Possible values are: <code>fail</code> (throw an exception | |||||
* and halt the build); <code>skip</code> (do not create | |||||
* any archive, but issue a warning); <code>create</code> | |||||
* (make an archive with no entries). | |||||
* Default for zip tasks is <code>skip</code>; | |||||
* for jar tasks, <code>create</code>. | |||||
*/ | |||||
public void setWhenempty(String we) throws BuildException { | |||||
we = we.toLowerCase(); | |||||
// XXX could instead be using EnumeratedAttribute, but this works | |||||
if (!"fail".equals(we) && !"skip".equals(we) && !"create".equals(we)) | |||||
throw new BuildException("Unrecognized whenempty attribute: " + we); | |||||
emptyBehavior = we; | |||||
} | |||||
DirectoryScanner ds = super.getDirectoryScanner(baseDir); | |||||
public void execute() throws BuildException { | |||||
if (baseDir == null && filesets.size() == 0) | |||||
throw new BuildException("basedir attribute must be set, or at least one fileset must be given!"); | |||||
String[] files = ds.getIncludedFiles(); | |||||
String[] dirs = ds.getIncludedDirectories(); | |||||
Vector dss = new Vector (); | |||||
if (baseDir != null) | |||||
dss.addElement(getDirectoryScanner(baseDir)); | |||||
for (int i=0; i<filesets.size(); i++) { | |||||
Object o = filesets.elementAt(i); | |||||
FileSet fs; | |||||
if (o instanceof FileSet) { | |||||
fs = (FileSet) o; | |||||
} else { | |||||
Reference r = (Reference) o; | |||||
o = r.getReferencedObject(project); | |||||
if (o instanceof FileSet) { | |||||
fs = (FileSet) o; | |||||
} else { | |||||
throw new BuildException(r.getRefId() + " does not denote a fileset", location); | |||||
} | |||||
} | |||||
dss.addElement (fs.getDirectoryScanner(project)); | |||||
} | |||||
FileScanner[] scanners = new FileScanner[dss.size()]; | |||||
dss.copyInto(scanners); | |||||
// quick exit if the target is up to date | // quick exit if the target is up to date | ||||
boolean upToDate = true; | |||||
for (int i=0; i<files.length && upToDate; i++) | |||||
if (new File(baseDir,files[i]).lastModified() > | |||||
zipFile.lastModified()) | |||||
upToDate = false; | |||||
if (upToDate) return; | |||||
// can also handle empty archives | |||||
if (isUpToDate(scanners, zipFile)) return; | |||||
log("Building "+ archiveType +": "+ zipFile.getAbsolutePath()); | log("Building "+ archiveType +": "+ zipFile.getAbsolutePath()); | ||||
ZipOutputStream zOut = null; | |||||
try { | |||||
zOut = new ZipOutputStream(new FileOutputStream(zipFile)); | |||||
if (doCompress) { | |||||
zOut.setMethod(ZipOutputStream.DEFLATED); | |||||
} else { | |||||
zOut.setMethod(ZipOutputStream.STORED); | |||||
} | |||||
initZipOutputStream(zOut); | |||||
try { | |||||
ZipOutputStream zOut = new ZipOutputStream(new FileOutputStream(zipFile)); | |||||
try { | |||||
if (doCompress) { | |||||
zOut.setMethod(ZipOutputStream.DEFLATED); | |||||
} else { | |||||
zOut.setMethod(ZipOutputStream.STORED); | |||||
} | |||||
initZipOutputStream(zOut); | |||||
for (int i = 0; i < dirs.length; i++) { | |||||
File f = new File(baseDir,dirs[i]); | |||||
String name = dirs[i].replace(File.separatorChar,'/')+"/"; | |||||
zipDir(f, zOut, name); | |||||
} | |||||
// XXX ideally would also enter includedDirectories to the archive | |||||
Hashtable parentDirs = new Hashtable(); | |||||
for (int i = 0; i < files.length; i++) { | |||||
File f = new File(baseDir,files[i]); | |||||
String name = files[i].replace(File.separatorChar,'/'); | |||||
zipFile(f, zOut, name); | |||||
} | |||||
} catch (IOException ioe) { | |||||
String msg = "Problem creating " + archiveType + " " + ioe.getMessage(); | |||||
for (int j = 0; j < scanners.length; j++) { | |||||
String[] files = scanners[j].getIncludedFiles(); | |||||
File thisBaseDir = scanners[j].getBasedir(); | |||||
for (int i = 0; i < files.length; i++) { | |||||
File f = new File(thisBaseDir,files[i]); | |||||
String name = files[i].replace(File.separatorChar,'/'); | |||||
// Look for & create parent dirs as needed. | |||||
int slashPos = -1; | |||||
while ((slashPos = name.indexOf((int)'/', slashPos + 1)) != -1) { | |||||
String dir = name.substring(0, slashPos); | |||||
if (!parentDirs.contains(dir)) { | |||||
parentDirs.put(dir, dir); | |||||
zipDir(new File(thisBaseDir, dir.replace('/', File.separatorChar)), | |||||
zOut, dir + '/'); | |||||
} | |||||
} | |||||
zipFile(f, zOut, name); | |||||
} | |||||
} | |||||
} finally { | |||||
zOut.close (); | |||||
} | |||||
} catch (IOException ioe) { | |||||
String msg = "Problem creating " + archiveType + ": " + ioe.getMessage(); | |||||
// delete a bogus ZIP file | // delete a bogus ZIP file | ||||
if (zOut != null) { | |||||
try { | |||||
zOut.close(); | |||||
zOut = null; | |||||
} catch (IOException e) {} | |||||
if (!zipFile.delete()) { | |||||
msg = zipFile + " is probably corrupt but I could not delete it"; | |||||
} | |||||
} | |||||
if (!zipFile.delete()) { | |||||
msg += " (and the archive is probably corrupt but I could not delete it)"; | |||||
} | |||||
throw new BuildException(msg, ioe, location); | throw new BuildException(msg, ioe, location); | ||||
} finally { | |||||
if (zOut != null) { | |||||
try { | |||||
// close up | |||||
zOut.close(); | |||||
} | |||||
catch (IOException e) {} | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -174,9 +220,87 @@ public class Zip extends MatchingTask { | |||||
{ | { | ||||
} | } | ||||
/** | |||||
* Check whether the archive is up-to-date; and handle behavior for empty archives. | |||||
* @param scanners list of prepared scanners containing files to archive | |||||
* @param zipFile intended archive file (may or may not exist) | |||||
* @return true if nothing need be done (may have done something already); false if | |||||
* archive creation should proceed | |||||
* @exception BuildException if it likes | |||||
*/ | |||||
protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException | |||||
{ | |||||
if (emptyBehavior == null) emptyBehavior = "skip"; | |||||
File[] files = grabFiles(scanners); | |||||
if (files.length == 0) { | |||||
if (emptyBehavior.equals("skip")) { | |||||
log("Warning: skipping ZIP archive " + zipFile + | |||||
" because no files were included.", Project.MSG_WARN); | |||||
return true; | |||||
} else if (emptyBehavior.equals("fail")) { | |||||
throw new BuildException("Cannot create ZIP archive " + zipFile + | |||||
": no files were included.", location); | |||||
} else { | |||||
// Create. | |||||
if (zipFile.exists()) return true; | |||||
// In this case using java.util.zip will not work | |||||
// because it does not permit a zero-entry archive. | |||||
// Must create it manually. | |||||
log("Note: creating empty ZIP archive " + zipFile, Project.MSG_INFO); | |||||
try { | |||||
OutputStream os = new FileOutputStream(zipFile); | |||||
try { | |||||
// Cf. PKZIP specification. | |||||
byte[] empty = new byte[22]; | |||||
empty[0] = 80; // P | |||||
empty[1] = 75; // K | |||||
empty[2] = 5; | |||||
empty[3] = 6; | |||||
// remainder zeros | |||||
os.write(empty); | |||||
} finally { | |||||
os.close(); | |||||
} | |||||
} catch (IOException ioe) { | |||||
throw new BuildException("Could not create empty ZIP archive", ioe, location); | |||||
} | |||||
return true; | |||||
} | |||||
} else { | |||||
// Probably unnecessary but just for clarity: | |||||
if (!zipFile.exists()) return false; | |||||
for (int i=0; i<files.length; i++) { | |||||
if (files[i].lastModified() > zipFile.lastModified()) { | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
} | |||||
protected static File[] grabFiles(FileScanner[] scanners) { | |||||
Vector files = new Vector (); | |||||
for (int i = 0; i < scanners.length; i++) { | |||||
File thisBaseDir = scanners[i].getBasedir(); | |||||
String[] ifiles = scanners[i].getIncludedFiles(); | |||||
for (int j = 0; j < ifiles.length; j++) | |||||
files.addElement(new File(thisBaseDir, ifiles[j])); | |||||
} | |||||
File[] toret = new File[files.size()]; | |||||
files.copyInto(toret); | |||||
return toret; | |||||
} | |||||
protected void zipDir(File dir, ZipOutputStream zOut, String vPath) | protected void zipDir(File dir, ZipOutputStream zOut, String vPath) | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
ZipEntry ze = new ZipEntry (vPath); | |||||
if (dir != null) ze.setTime (dir.lastModified ()); | |||||
ze.setSize (0); | |||||
ze.setMethod (ZipEntry.STORED); | |||||
// This is faintly ridiculous: | |||||
ze.setCrc (emptyCrc); | |||||
zOut.putNextEntry (ze); | |||||
} | } | ||||
protected void zipFile(InputStream in, ZipOutputStream zOut, String vPath, | protected void zipFile(InputStream in, ZipOutputStream zOut, String vPath, | ||||