diff --git a/WHATSNEW b/WHATSNEW index f2ea3d05b..57b8a9fab 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -253,6 +253,9 @@ Other changes: * Add else attribute to the condition task, which specifies an optional alternate value to set the property to if the nested condition evaluates to false. Bugzilla report 33074. + +* Ant generated jar files should now be detected as jar files by + Solaris. Bugzilla Report 32649. Fixed bugs: ----------- diff --git a/src/main/org/apache/tools/ant/taskdefs/Jar.java b/src/main/org/apache/tools/ant/taskdefs/Jar.java index b33a5162d..eceb73fb2 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Jar.java +++ b/src/main/org/apache/tools/ant/taskdefs/Jar.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2004 The Apache Software Foundation + * Copyright 2000-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +47,8 @@ import org.apache.tools.ant.types.EnumeratedAttribute; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.ZipFileSet; +import org.apache.tools.zip.JarMarker; +import org.apache.tools.zip.ZipExtraField; import org.apache.tools.zip.ZipOutputStream; /** @@ -130,6 +132,15 @@ public class Jar extends Zip { */ private Path indexJars; + /** + * Extra fields needed to make Solaris recognize the archive as a jar file. + * + * @since Ant 1.6.3 + */ + private ZipExtraField[] JAR_MARKER = new ZipExtraField[] { + JarMarker.getInstance() + }; + /** constructor */ public Jar() { super(); @@ -382,7 +393,8 @@ public class Jar extends Zip { Project.MSG_WARN); } - zipDir(null, zOut, "META-INF/", ZipFileSet.DEFAULT_DIR_MODE); + zipDir(null, zOut, "META-INF/", ZipFileSet.DEFAULT_DIR_MODE, + JAR_MARKER); // time to write the manifest ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(baos, "UTF-8"); diff --git a/src/main/org/apache/tools/ant/taskdefs/Zip.java b/src/main/org/apache/tools/ant/taskdefs/Zip.java index 739dc3379..4698b9a98 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Zip.java +++ b/src/main/org/apache/tools/ant/taskdefs/Zip.java @@ -47,6 +47,7 @@ import org.apache.tools.ant.util.IdentityMapper; import org.apache.tools.ant.util.MergingMapper; import org.apache.tools.ant.util.ResourceUtils; import org.apache.tools.zip.ZipEntry; +import org.apache.tools.zip.ZipExtraField; import org.apache.tools.zip.ZipFile; import org.apache.tools.zip.ZipOutputStream; @@ -1030,6 +1031,22 @@ public class Zip extends MatchingTask { protected void zipDir(File dir, ZipOutputStream zOut, String vPath, int mode) throws IOException { + zipDir(dir, zOut, vPath, mode, null); + } + + /** + * Add a directory to the zip stream. + * @param dir the directort to add to the archive + * @param zOut the stream to write to + * @param vPath the name this entry shall have in the archive + * @param mode the Unix permissions to set. + * @param extra ZipExtraFields to add + * @throws IOException on error + * @since Ant 1.6.3 + */ + protected void zipDir(File dir, ZipOutputStream zOut, String vPath, + int mode, ZipExtraField[] extra) + throws IOException { if (addedDirs.get(vPath) != null) { // don't add directories we've already added. // no warning if we try, it is harmless in and of itself @@ -1054,7 +1071,11 @@ public class Zip extends MatchingTask { ze.setCrc (EMPTY_CRC); ze.setUnixMode(mode); - zOut.putNextEntry (ze); + if (extra != null) { + ze.setExtraFields(extra); + } + + zOut.putNextEntry(ze); } } diff --git a/src/main/org/apache/tools/zip/ExtraFieldUtils.java b/src/main/org/apache/tools/zip/ExtraFieldUtils.java index fe98dae3e..3b53f1784 100644 --- a/src/main/org/apache/tools/zip/ExtraFieldUtils.java +++ b/src/main/org/apache/tools/zip/ExtraFieldUtils.java @@ -37,6 +37,7 @@ public class ExtraFieldUtils { static { implementations = new Hashtable(); register(AsiExtraField.class); + register(JarMarker.class); } /** diff --git a/src/main/org/apache/tools/zip/JarMarker.java b/src/main/org/apache/tools/zip/JarMarker.java new file mode 100644 index 000000000..07a344235 --- /dev/null +++ b/src/main/org/apache/tools/zip/JarMarker.java @@ -0,0 +1,105 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * 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 org.apache.tools.zip; + +import java.util.zip.ZipException; + +/** + * If this extra field is added as the very first extra field of the + * archive, Solaris will consider it an executable jar file. + * + * @since Ant 1.6.3 + */ +public final class JarMarker implements ZipExtraField { + + private static ZipShort ID = new ZipShort(0xCAFE); + private static ZipShort NULL = new ZipShort(0); + private static byte[] NO_BYTES = new byte[0]; + private static JarMarker DEFAULT = new JarMarker(); + + public JarMarker() { + // empty + } + + /** + * Since JarMarker is stateless we can always use the same instance. + */ + public static JarMarker getInstance() { + return DEFAULT; + } + + /** + * The Header-ID. + * @return the header id + */ + public ZipShort getHeaderId() { + return ID; + } + + /** + * Length of the extra field in the local file data - without + * Header-ID or length specifier. + * @return 0 + */ + public ZipShort getLocalFileDataLength() { + return NULL; + } + + /** + * Length of the extra field in the central directory - without + * Header-ID or length specifier. + * @return 0 + */ + public ZipShort getCentralDirectoryLength() { + return NULL; + } + + /** + * The actual data to put into local file data - without Header-ID + * or length specifier. + * @return the data + * @since 1.1 + */ + public byte[] getLocalFileDataData() { + return NO_BYTES; + } + + /** + * The actual data to put central directory - without Header-ID or + * length specifier. + * @return the data + */ + public byte[] getCentralDirectoryData() { + return NO_BYTES; + } + + /** + * Populate data from this array as if it was in local file data. + * @param data an array of bytes + * @param offset the start offset + * @param length the number of bytes in the array from offset + * + * @throws ZipException on error + */ + public void parseFromLocalFileData(byte[] data, int offset, int length) + throws ZipException { + if (length != 0) { + throw new ZipException("JarMarker doesn't expect any data"); + } + } +}