001 /*
002 * Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.util.zip;
027
028 import java.util.Date;
029
030 /**
031 * This class is used to represent a ZIP file entry.
032 *
033 * @version 1.46, 05/05/07
034 * @author David Connelly
035 */
036 public class ZipEntry implements ZipConstants, Cloneable {
037 String name; // entry name
038 long time = -1; // modification time (in DOS time)
039 long crc = -1; // crc-32 of entry data
040 long size = -1; // uncompressed size of entry data
041 long csize = -1; // compressed size of entry data
042 int method = -1; // compression method
043 byte[] extra; // optional extra field data for entry
044 String comment; // optional comment string for entry
045
046 /**
047 * Compression method for uncompressed entries.
048 */
049 public static final int STORED = 0;
050
051 /**
052 * Compression method for compressed (deflated) entries.
053 */
054 public static final int DEFLATED = 8;
055
056 static {
057 /* Zip library is loaded from System.initializeSystemClass */
058 initIDs();
059 }
060
061 private static native void initIDs();
062
063 /**
064 * Creates a new zip entry with the specified name.
065 *
066 * @param name the entry name
067 * @exception NullPointerException if the entry name is null
068 * @exception IllegalArgumentException if the entry name is longer than
069 * 0xFFFF bytes
070 */
071 public ZipEntry(String name) {
072 if (name == null) {
073 throw new NullPointerException();
074 }
075 if (name.length() > 0xFFFF) {
076 throw new IllegalArgumentException("entry name too long");
077 }
078 this .name = name;
079 }
080
081 /**
082 * Creates a new zip entry with fields taken from the specified
083 * zip entry.
084 * @param e a zip Entry object
085 */
086 public ZipEntry(ZipEntry e) {
087 name = e.name;
088 time = e.time;
089 crc = e.crc;
090 size = e.size;
091 csize = e.csize;
092 method = e.method;
093 extra = e.extra;
094 comment = e.comment;
095 }
096
097 /*
098 * Creates a new zip entry for the given name with fields initialized
099 * from the specified jzentry data.
100 */
101 ZipEntry(String name, long jzentry) {
102 this .name = name;
103 initFields(jzentry);
104 }
105
106 private native void initFields(long jzentry);
107
108 /*
109 * Creates a new zip entry with fields initialized from the specified
110 * jzentry data.
111 */
112 ZipEntry(long jzentry) {
113 initFields(jzentry);
114 }
115
116 /**
117 * Returns the name of the entry.
118 * @return the name of the entry
119 */
120 public String getName() {
121 return name;
122 }
123
124 /**
125 * Sets the modification time of the entry.
126 * @param time the entry modification time in number of milliseconds
127 * since the epoch
128 * @see #getTime()
129 */
130 public void setTime(long time) {
131 this .time = javaToDosTime(time);
132 }
133
134 /**
135 * Returns the modification time of the entry, or -1 if not specified.
136 * @return the modification time of the entry, or -1 if not specified
137 * @see #setTime(long)
138 */
139 public long getTime() {
140 return time != -1 ? dosToJavaTime(time) : -1;
141 }
142
143 /**
144 * Sets the uncompressed size of the entry data.
145 * @param size the uncompressed size in bytes
146 * @exception IllegalArgumentException if the specified size is less
147 * than 0 or greater than 0xFFFFFFFF bytes
148 * @see #getSize()
149 */
150 public void setSize(long size) {
151 if (size < 0 || size > 0xFFFFFFFFL) {
152 throw new IllegalArgumentException("invalid entry size");
153 }
154 this .size = size;
155 }
156
157 /**
158 * Returns the uncompressed size of the entry data, or -1 if not known.
159 * @return the uncompressed size of the entry data, or -1 if not known
160 * @see #setSize(long)
161 */
162 public long getSize() {
163 return size;
164 }
165
166 /**
167 * Returns the size of the compressed entry data, or -1 if not known.
168 * In the case of a stored entry, the compressed size will be the same
169 * as the uncompressed size of the entry.
170 * @return the size of the compressed entry data, or -1 if not known
171 * @see #setCompressedSize(long)
172 */
173 public long getCompressedSize() {
174 return csize;
175 }
176
177 /**
178 * Sets the size of the compressed entry data.
179 * @param csize the compressed size to set to
180 * @see #getCompressedSize()
181 */
182 public void setCompressedSize(long csize) {
183 this .csize = csize;
184 }
185
186 /**
187 * Sets the CRC-32 checksum of the uncompressed entry data.
188 * @param crc the CRC-32 value
189 * @exception IllegalArgumentException if the specified CRC-32 value is
190 * less than 0 or greater than 0xFFFFFFFF
191 * @see #getCrc()
192 */
193 public void setCrc(long crc) {
194 if (crc < 0 || crc > 0xFFFFFFFFL) {
195 throw new IllegalArgumentException("invalid entry crc-32");
196 }
197 this .crc = crc;
198 }
199
200 /**
201 * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
202 * not known.
203 * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
204 * not known
205 * @see #setCrc(long)
206 */
207 public long getCrc() {
208 return crc;
209 }
210
211 /**
212 * Sets the compression method for the entry.
213 * @param method the compression method, either STORED or DEFLATED
214 * @exception IllegalArgumentException if the specified compression
215 * method is invalid
216 * @see #getMethod()
217 */
218 public void setMethod(int method) {
219 if (method != STORED && method != DEFLATED) {
220 throw new IllegalArgumentException(
221 "invalid compression method");
222 }
223 this .method = method;
224 }
225
226 /**
227 * Returns the compression method of the entry, or -1 if not specified.
228 * @return the compression method of the entry, or -1 if not specified
229 * @see #setMethod(int)
230 */
231 public int getMethod() {
232 return method;
233 }
234
235 /**
236 * Sets the optional extra field data for the entry.
237 * @param extra the extra field data bytes
238 * @exception IllegalArgumentException if the length of the specified
239 * extra field data is greater than 0xFFFF bytes
240 * @see #getExtra()
241 */
242 public void setExtra(byte[] extra) {
243 if (extra != null && extra.length > 0xFFFF) {
244 throw new IllegalArgumentException(
245 "invalid extra field length");
246 }
247 this .extra = extra;
248 }
249
250 /**
251 * Returns the extra field data for the entry, or null if none.
252 * @return the extra field data for the entry, or null if none
253 * @see #setExtra(byte[])
254 */
255 public byte[] getExtra() {
256 return extra;
257 }
258
259 /**
260 * Sets the optional comment string for the entry.
261 * @param comment the comment string
262 * @exception IllegalArgumentException if the length of the specified
263 * comment string is greater than 0xFFFF bytes
264 * @see #getComment()
265 */
266 public void setComment(String comment) {
267 if (comment != null && comment.length() > 0xffff / 3
268 && ZipOutputStream.getUTF8Length(comment) > 0xffff) {
269 throw new IllegalArgumentException(
270 "invalid entry comment length");
271 }
272 this .comment = comment;
273 }
274
275 /**
276 * Returns the comment string for the entry, or null if none.
277 * @return the comment string for the entry, or null if none
278 * @see #setComment(String)
279 */
280 public String getComment() {
281 return comment;
282 }
283
284 /**
285 * Returns true if this is a directory entry. A directory entry is
286 * defined to be one whose name ends with a '/'.
287 * @return true if this is a directory entry
288 */
289 public boolean isDirectory() {
290 return name.endsWith("/");
291 }
292
293 /**
294 * Returns a string representation of the ZIP entry.
295 */
296 public String toString() {
297 return getName();
298 }
299
300 /*
301 * Converts DOS time to Java time (number of milliseconds since epoch).
302 */
303 private static long dosToJavaTime(long dtime) {
304 Date d = new Date((int) (((dtime >> 25) & 0x7f) + 80),
305 (int) (((dtime >> 21) & 0x0f) - 1),
306 (int) ((dtime >> 16) & 0x1f),
307 (int) ((dtime >> 11) & 0x1f),
308 (int) ((dtime >> 5) & 0x3f),
309 (int) ((dtime << 1) & 0x3e));
310 return d.getTime();
311 }
312
313 /*
314 * Converts Java time to DOS time.
315 */
316 private static long javaToDosTime(long time) {
317 Date d = new Date(time);
318 int year = d.getYear() + 1900;
319 if (year < 1980) {
320 return (1 << 21) | (1 << 16);
321 }
322 return (year - 1980) << 25 | (d.getMonth() + 1) << 21
323 | d.getDate() << 16 | d.getHours() << 11
324 | d.getMinutes() << 5 | d.getSeconds() >> 1;
325 }
326
327 /**
328 * Returns the hash code value for this entry.
329 */
330 public int hashCode() {
331 return name.hashCode();
332 }
333
334 /**
335 * Returns a copy of this entry.
336 */
337 public Object clone() {
338 try {
339 ZipEntry e = (ZipEntry) super .clone();
340 e.extra = (extra == null ? null : (byte[]) extra.clone());
341 return e;
342 } catch (CloneNotSupportedException e) {
343 // This should never happen, since we are Cloneable
344 throw new InternalError();
345 }
346 }
347 }
|