make the classes flexible enough to deal with non US-ASCII filenames either consistent with the command line ZIP tools (it has been since it uses the org.apache classes instead of java.util.zip) or the jar command (which it has been up to Ant 1.3). git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269272 13f79535-47bb-0310-9956-ffa450edef68master
@@ -12,6 +12,12 @@ Changes that could break older environments: | |||||
* several Zip methods have changed their signature as we now use a Zip | * several Zip methods have changed their signature as we now use a Zip | ||||
package of our own that handles Unix permissions for directories. | package of our own that handles Unix permissions for directories. | ||||
Furthermore <zip> will now use the platform's default character | |||||
encoding for filenames - this is consistent with the command line | |||||
ZIP tools, but causes problems if you try to open them from within | |||||
Java and your filenames contain non US-ASCII characters. Use the new | |||||
encoding attribute of the task and set it to UTF8 to get the old | |||||
behavior. | |||||
* The <pvcs> task has been move to a package of its own. | * The <pvcs> task has been move to a package of its own. | ||||
@@ -43,6 +43,14 @@ attributes of zipfilesets in a Zip or Jar task.)</p> | |||||
<td valign="top">Not only store data but also compress them, defaults to true</td> | <td valign="top">Not only store data but also compress them, defaults to true</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">encoding</td> | |||||
<td valign="top">The character encoding to use for filenames | |||||
inside the archive. Defaults to UTF8. <strong>It is not | |||||
recommended to change this value as the created archive will most | |||||
likely be unreadable for Java otherwise.</strong></td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">includes</td> | <td valign="top">includes</td> | ||||
<td valign="top">comma separated list of patterns of files that must be | <td valign="top">comma separated list of patterns of files that must be | ||||
@@ -65,6 +65,14 @@ include an empty one for you.)</p> | |||||
<td valign="top">Not only store data but also compress them, defaults to true</td> | <td valign="top">Not only store data but also compress them, defaults to true</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">encoding</td> | |||||
<td valign="top">The character encoding to use for filenames | |||||
inside the archive. Defaults to UTF8. <strong>It is not | |||||
recommended to change this value as the created archive will most | |||||
likely be unreadable for Java otherwise.</strong></td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">includes</td> | <td valign="top">includes</td> | ||||
<td valign="top">comma separated list of patterns of files that must be | <td valign="top">comma separated list of patterns of files that must be | ||||
@@ -45,6 +45,14 @@ attributes of zipfilesets in a Zip or Jar task.)</p> | |||||
<td valign="top">Not only store data but also compress them, defaults to true</td> | <td valign="top">Not only store data but also compress them, defaults to true</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">encoding</td> | |||||
<td valign="top">The character encoding to use for filenames | |||||
inside the archive. Defaults to UTF8. <strong>It is not | |||||
recommended to change this value as the created archive will most | |||||
likely be unreadable for Java otherwise.</strong></td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">includes</td> | <td valign="top">includes</td> | ||||
<td valign="top">comma separated list of patterns of files that must be | <td valign="top">comma separated list of patterns of files that must be | ||||
@@ -38,6 +38,12 @@ If <code>skip</code> (the default), the ZIP is not created and a warning is issu | |||||
If <code>fail</code>, the ZIP is not created and the build is halted with an error. | 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, | 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> | which should be recognized as such by compliant ZIP manipulation tools.</p> | ||||
<p>This task will now use the platform's default character encoding | |||||
for filenames - this is consistent with the command line ZIP tools, | |||||
but causes problems if you try to open them from within Java and your | |||||
filenames contain non US-ASCII characters. Use the encoding attribute | |||||
and set it to UTF8 to create zip files that can savely be read by | |||||
Java.</p> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -60,6 +66,14 @@ which should be recognized as such by compliant ZIP manipulation tools.</p> | |||||
<td valign="top">Not only store data but also compress them, defaults to true</td> | <td valign="top">Not only store data but also compress them, defaults to true</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">encoding</td> | |||||
<td valign="top">The character encoding to use for filenames | |||||
inside the zip file. For a list of possible values see <a | |||||
href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html</a>. | |||||
Defaults to the platform's default character encoding.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">includes</td> | <td valign="top">includes</td> | ||||
<td valign="top">comma separated list of patterns of files that must be | <td valign="top">comma separated list of patterns of files that must be | ||||
@@ -75,6 +75,7 @@ public class Jar extends Zip { | |||||
super(); | super(); | ||||
archiveType = "jar"; | archiveType = "jar"; | ||||
emptyBehavior = "create"; | emptyBehavior = "create"; | ||||
setEncoding("UTF8"); | |||||
} | } | ||||
public void setJarfile(File jarFile) { | public void setJarfile(File jarFile) { | ||||
@@ -85,6 +85,12 @@ public class Zip extends MatchingTask { | |||||
private Vector filesets = new Vector (); | private Vector filesets = new Vector (); | ||||
private Hashtable addedDirs = new Hashtable(); | private Hashtable addedDirs = new Hashtable(); | ||||
/** | |||||
* Encoding to use for filenames, defaults to the platform's | |||||
* default encoding. | |||||
*/ | |||||
private String encoding = null; | |||||
/** | /** | ||||
* This is the name/location of where to | * This is the name/location of where to | ||||
* create the .zip file. | * create the .zip file. | ||||
@@ -144,6 +150,17 @@ public class Zip extends MatchingTask { | |||||
emptyBehavior = we.getValue(); | emptyBehavior = we.getValue(); | ||||
} | } | ||||
/** | |||||
* Encoding to use for filenames, defaults to the platform's | |||||
* default encoding. | |||||
* | |||||
* <p>For a list of possible values see <a | |||||
* href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html</a>.</p> | |||||
*/ | |||||
public void setEncoding(String encoding) { | |||||
this.encoding = encoding; | |||||
} | |||||
public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
if (baseDir == null && filesets.size() == 0 && "zip".equals(archiveType)) { | if (baseDir == null && filesets.size() == 0 && "zip".equals(archiveType)) { | ||||
throw new BuildException( "basedir attribute must be set, or at least " + | throw new BuildException( "basedir attribute must be set, or at least " + | ||||
@@ -176,6 +193,7 @@ public class Zip extends MatchingTask { | |||||
boolean success = false; | boolean success = false; | ||||
ZipOutputStream zOut = | ZipOutputStream zOut = | ||||
new ZipOutputStream(new FileOutputStream(zipFile)); | new ZipOutputStream(new FileOutputStream(zipFile)); | ||||
zOut.setEncoding(encoding); | |||||
try { | try { | ||||
if (doCompress) { | if (doCompress) { | ||||
zOut.setMethod(ZipOutputStream.DEFLATED); | zOut.setMethod(ZipOutputStream.DEFLATED); | ||||
@@ -173,6 +173,17 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
*/ | */ | ||||
private Hashtable offsets = new Hashtable(); | private Hashtable offsets = new Hashtable(); | ||||
/** | |||||
* The encoding to use for filenames and the file comment. | |||||
* | |||||
* <p>For a list of possible values see <a | |||||
* href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html</a>. | |||||
* Defaults to the platform's default character encoding.</p> | |||||
* | |||||
* @since 1.3 | |||||
*/ | |||||
private String encoding = null; | |||||
/** | /** | ||||
* Compression method for deflated entries. | * Compression method for deflated entries. | ||||
* | * | ||||
@@ -196,10 +207,32 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); | super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); | ||||
} | } | ||||
/** | |||||
* The encoding to use for filenames and the file comment. | |||||
* | |||||
* <p>For a list of possible values see <a | |||||
* href="http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html">http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html</a>. | |||||
* Defaults to the platform's default character encoding.</p> | |||||
* | |||||
* @since 1.3 | |||||
*/ | |||||
public void setEncoding(String encoding) { | |||||
this.encoding = encoding; | |||||
} | |||||
/** | |||||
* The encoding to use for filenames and the file comment. | |||||
* | |||||
* @return null if using the platform's default character encoding. | |||||
* | |||||
* @since 1.3 | |||||
*/ | |||||
public String getEncoding() {return encoding;} | |||||
/* | /* | ||||
* Found out by experiment, that DeflaterOutputStream.close() | * Found out by experiment, that DeflaterOutputStream.close() | ||||
* will call finish() - so we don't need to override close | * will call finish() - so we don't need to override close | ||||
* ourselves.</p> | |||||
* ourselves. | |||||
*/ | */ | ||||
/** | /** | ||||
@@ -426,7 +459,7 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
written += 12; | written += 12; | ||||
// file name length | // file name length | ||||
byte[] name = ze.getName().getBytes(); | |||||
byte[] name = getBytes(ze.getName()); | |||||
out.write((new ZipShort(name.length)).getBytes()); | out.write((new ZipShort(name.length)).getBytes()); | ||||
written += 2; | written += 2; | ||||
@@ -507,7 +540,7 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
written += 12; | written += 12; | ||||
// file name length | // file name length | ||||
byte[] name = ze.getName().getBytes(); | |||||
byte[] name = getBytes(ze.getName()); | |||||
out.write((new ZipShort(name.length)).getBytes()); | out.write((new ZipShort(name.length)).getBytes()); | ||||
written += 2; | written += 2; | ||||
@@ -521,7 +554,7 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
if (comm == null) { | if (comm == null) { | ||||
comm = ""; | comm = ""; | ||||
} | } | ||||
byte[] comment = comm.getBytes(); | |||||
byte[] comment = getBytes(comm); | |||||
out.write((new ZipShort(comment.length)).getBytes()); | out.write((new ZipShort(comment.length)).getBytes()); | ||||
written += 2; | written += 2; | ||||
@@ -576,7 +609,7 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
out.write(cdOffset.getBytes()); | out.write(cdOffset.getBytes()); | ||||
// ZIP file comment | // ZIP file comment | ||||
byte[] data = comment.getBytes(); | |||||
byte[] data = getBytes(comment); | |||||
out.write((new ZipShort(data.length)).getBytes()); | out.write((new ZipShort(data.length)).getBytes()); | ||||
out.write(data); | out.write(data); | ||||
} | } | ||||
@@ -616,4 +649,22 @@ public class ZipOutputStream extends DeflaterOutputStream { | |||||
return new ZipLong(result); | return new ZipLong(result); | ||||
} | } | ||||
/** | |||||
* Retrieve the bytes for the given String in the encoding set for | |||||
* this Stream. | |||||
* | |||||
* @since 1.3 | |||||
*/ | |||||
protected byte[] getBytes(String name) throws ZipException { | |||||
if (encoding == null) { | |||||
return name.getBytes(); | |||||
} else { | |||||
try { | |||||
return name.getBytes(encoding); | |||||
} catch (UnsupportedEncodingException uee) { | |||||
throw new ZipException(uee.getMessage()); | |||||
} | |||||
} | |||||
} | |||||
} | } |