2 Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.util.zip;
41 import java.util.Calendar;
44 * This class represents a member of a zip archive. ZipFile and
45 * ZipInputStream will give you instances of this class as information
46 * about the members in an archive. On the other hand ZipOutputStream
47 * needs an instance of this class to create a new member.
49 * @author Jochen Hoenicke
51 public class ZipEntry implements ZipConstants, Cloneable
53 private static final byte KNOWN_SIZE = 1;
54 private static final byte KNOWN_CSIZE = 2;
55 private static final byte KNOWN_CRC = 4;
56 private static final byte KNOWN_TIME = 8;
57 private static final byte KNOWN_DOSTIME = 16;
58 private static final byte KNOWN_EXTRA = 32;
60 /** Immutable name of the entry */
61 private final String name;
62 /** Uncompressed size */
64 /** Compressed size */
65 private long compressedSize = -1;
66 /** CRC of uncompressed data */
68 /** Comment or null if none */
69 private String comment = null;
70 /** The compression method. Either DEFLATED or STORED, by default -1. */
71 private byte method = -1;
72 /** Flags specifying what we know about this entry */
73 private byte known = 0;
75 * The 32bit DOS encoded format for the time of this entry. Only valid if
76 * KNOWN_DOSTIME is set in known.
80 * The 64bit Java encoded millisecond time since the beginning of the epoch.
81 * Only valid if KNOWN_TIME is set in known.
85 private byte[] extra = null;
87 int flags; /* used by ZipOutputStream */
88 int offset; /* used by ZipFile and ZipOutputStream */
91 * Compression method. This method doesn't compress at all.
93 public static final int STORED = 0;
95 * Compression method. This method uses the Deflater.
97 public static final int DEFLATED = 8;
100 * Creates a zip entry with the given name.
101 * @param name the name. May include directory components separated
104 * @exception NullPointerException when name is null.
105 * @exception IllegalArgumentException when name is bigger then 65535 chars.
107 public ZipEntry(String name)
109 int length = name.length();
111 throw new IllegalArgumentException("name length is " + length);
116 * Creates a copy of the given zip entry.
117 * @param e the entry to copy.
119 public ZipEntry(ZipEntry e)
124 ZipEntry(ZipEntry e, String name)
129 compressedSize = e.compressedSize;
138 final void setDOSTime(int dostime)
140 this.dostime = dostime;
141 known |= KNOWN_DOSTIME;
142 known &= ~KNOWN_TIME;
145 final int getDOSTime()
147 if ((known & KNOWN_DOSTIME) != 0)
149 else if ((known & KNOWN_TIME) != 0)
151 Calendar cal = Calendar.getInstance();
152 cal.setTimeInMillis(time);
153 dostime = (cal.get(Calendar.YEAR) - 1980 & 0x7f) << 25
154 | (cal.get(Calendar.MONTH) + 1) << 21
155 | (cal.get(Calendar.DAY_OF_MONTH)) << 16
156 | (cal.get(Calendar.HOUR_OF_DAY)) << 11
157 | (cal.get(Calendar.MINUTE)) << 5
158 | (cal.get(Calendar.SECOND)) >> 1;
159 known |= KNOWN_DOSTIME;
167 * Creates a copy of this zip entry.
169 public Object clone()
171 // JCL defines this as being the same as the copy constructor above,
172 // except that value of the "extra" field is also copied. Take care
173 // that in the case of a subclass we use clone() rather than the copy
176 if (this.getClass() == ZipEntry.class)
177 clone = new ZipEntry(this);
182 clone = (ZipEntry) super.clone();
184 catch (CloneNotSupportedException e)
186 throw new InternalError();
191 clone.extra = new byte[extra.length];
192 System.arraycopy(extra, 0, clone.extra, 0, extra.length);
198 * Returns the entry name. The path components in the entry are
199 * always separated by slashes ('/').
201 public String getName()
207 * Sets the time of last modification of the entry.
208 * @time the time of last modification of the entry.
210 public void setTime(long time)
213 this.known |= KNOWN_TIME;
214 this.known &= ~KNOWN_DOSTIME;
218 * Gets the time of last modification of the entry.
219 * @return the time of last modification of the entry, or -1 if unknown.
221 public long getTime()
223 // The extra bytes might contain the time (posix/unix extension)
226 if ((known & KNOWN_TIME) != 0)
228 else if ((known & KNOWN_DOSTIME) != 0)
230 int sec = 2 * (dostime & 0x1f);
231 int min = (dostime >> 5) & 0x3f;
232 int hrs = (dostime >> 11) & 0x1f;
233 int day = (dostime >> 16) & 0x1f;
234 int mon = ((dostime >> 21) & 0xf) - 1;
235 int year = ((dostime >> 25) & 0x7f) + 1980; /* since 1900 */
239 Calendar cal = Calendar.getInstance();
240 cal.set(year, mon, day, hrs, min, sec);
241 time = cal.getTimeInMillis();
245 catch (RuntimeException ex)
247 /* Ignore illegal time stamp */
248 known &= ~KNOWN_TIME;
257 * Sets the size of the uncompressed data.
258 * @exception IllegalArgumentException if size is not in 0..0xffffffffL
260 public void setSize(long size)
262 if ((size & 0xffffffff00000000L) != 0)
263 throw new IllegalArgumentException();
264 this.size = (int) size;
265 this.known |= KNOWN_SIZE;
269 * Gets the size of the uncompressed data.
270 * @return the size or -1 if unknown.
272 public long getSize()
274 return (known & KNOWN_SIZE) != 0 ? size & 0xffffffffL : -1L;
278 * Sets the size of the compressed data.
280 public void setCompressedSize(long csize)
282 this.compressedSize = csize;
286 * Gets the size of the compressed data.
287 * @return the size or -1 if unknown.
289 public long getCompressedSize()
291 return compressedSize;
295 * Sets the crc of the uncompressed data.
296 * @exception IllegalArgumentException if crc is not in 0..0xffffffffL
298 public void setCrc(long crc)
300 if ((crc & 0xffffffff00000000L) != 0)
301 throw new IllegalArgumentException();
302 this.crc = (int) crc;
303 this.known |= KNOWN_CRC;
307 * Gets the crc of the uncompressed data.
308 * @return the crc or -1 if unknown.
312 return (known & KNOWN_CRC) != 0 ? crc & 0xffffffffL : -1L;
316 * Sets the compression method. Only DEFLATED and STORED are
318 * @exception IllegalArgumentException if method is not supported.
319 * @see ZipOutputStream#DEFLATED
320 * @see ZipOutputStream#STORED
322 public void setMethod(int method)
324 if (method != ZipOutputStream.STORED
325 && method != ZipOutputStream.DEFLATED)
326 throw new IllegalArgumentException();
327 this.method = (byte) method;
331 * Gets the compression method.
332 * @return the compression method or -1 if unknown.
334 public int getMethod()
340 * Sets the extra data.
341 * @exception IllegalArgumentException if extra is longer than 0xffff bytes.
343 public void setExtra(byte[] extra)
350 if (extra.length > 0xffff)
351 throw new IllegalArgumentException();
355 private void parseExtra()
358 if ((known & KNOWN_EXTRA) != 0)
363 known |= KNOWN_EXTRA;
370 while (pos < extra.length)
372 int sig = (extra[pos++] & 0xff)
373 | (extra[pos++] & 0xff) << 8;
374 int len = (extra[pos++] & 0xff)
375 | (extra[pos++] & 0xff) << 8;
378 /* extended time stamp */
379 int flags = extra[pos];
380 if ((flags & 1) != 0)
382 long time = ((extra[pos+1] & 0xff)
383 | (extra[pos+2] & 0xff) << 8
384 | (extra[pos+3] & 0xff) << 16
385 | (extra[pos+4] & 0xff) << 24);
392 catch (ArrayIndexOutOfBoundsException ex)
397 known |= KNOWN_EXTRA;
402 * Gets the extra data.
403 * @return the extra data or null if not set.
405 public byte[] getExtra()
411 * Sets the entry comment.
412 * @exception IllegalArgumentException if comment is longer than 0xffff.
414 public void setComment(String comment)
416 if (comment != null && comment.length() > 0xffff)
417 throw new IllegalArgumentException();
418 this.comment = comment;
423 * @return the comment or null if not set.
425 public String getComment()
431 * Gets true, if the entry is a directory. This is solely
432 * determined by the name, a trailing slash '/' marks a directory.
434 public boolean isDirectory()
436 int nlen = name.length();
437 return nlen > 0 && name.charAt(nlen - 1) == '/';
441 * Gets the string representation of this ZipEntry. This is just
442 * the name as returned by getName().
444 public String toString()
450 * Gets the hashCode of this ZipEntry. This is just the hashCode
451 * of the name. Note that the equals method isn't changed, though.
453 public int hashCode()
455 return name.hashCode();