KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > codecoverage > v2 > ant > zip > ZipEntry


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17
18 package net.sourceforge.groboutils.codecoverage.v2.ant.zip;
19
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.util.Vector JavaDoc;
23 import java.util.zip.ZipException JavaDoc;
24
25 /**
26  * Extension that adds better handling of extra fields and provides
27  * access to the internal and external file attributes.
28  *
29  * @author Stefan Bodewig
30  * @version $Revision: 1.1 $
31  */

32 public class ZipEntry extends java.util.zip.ZipEntry JavaDoc implements Cloneable JavaDoc {
33
34     private static final int PLATFORM_UNIX = 3;
35     private static final int PLATFORM_FAT = 0;
36
37     private int internalAttributes = 0;
38     private int platform = PLATFORM_FAT;
39     private long externalAttributes = 0;
40     private Vector JavaDoc extraFields = new Vector JavaDoc();
41     private String JavaDoc name = null;
42
43     /**
44      * Creates a new zip entry with the specified name.
45      *
46      * @since 1.1
47      */

48     public ZipEntry(String JavaDoc name) {
49         super(name);
50     }
51
52     /**
53      * Creates a new zip entry with fields taken from the specified zip entry.
54      *
55      * @since 1.1
56      */

57     public ZipEntry(java.util.zip.ZipEntry JavaDoc entry) throws ZipException JavaDoc {
58         /*
59          * REVISIT: call super(entry) instead of this stuff in Ant2,
60          * "copy constructor" has not been available in JDK 1.1
61          */

62         super(entry.getName());
63
64         setComment(entry.getComment());
65         setMethod(entry.getMethod());
66         setTime(entry.getTime());
67
68         long size = entry.getSize();
69         if (size > 0) {
70             setSize(size);
71         }
72         long cSize = entry.getCompressedSize();
73         if (cSize > 0) {
74             setComprSize(cSize);
75         }
76         long crc = entry.getCrc();
77         if (crc > 0) {
78             setCrc(crc);
79         }
80
81         byte[] extra = entry.getExtra();
82         if (extra != null) {
83             setExtraFields(ExtraFieldUtils.parse(extra));
84         } else {
85             // initializes extra data to an empty byte array
86
setExtra();
87         }
88     }
89
90     /**
91      * Creates a new zip entry with fields taken from the specified zip entry.
92      *
93      * @since 1.1
94      */

95     public ZipEntry(ZipEntry entry) throws ZipException JavaDoc {
96         this((java.util.zip.ZipEntry JavaDoc) entry);
97         setInternalAttributes(entry.getInternalAttributes());
98         setExternalAttributes(entry.getExternalAttributes());
99         setExtraFields(entry.getExtraFields());
100     }
101
102     /**
103      * @since 1.9
104      */

105     protected ZipEntry() {
106         super("");
107     }
108
109     /**
110      * Overwrite clone
111      *
112      * @since 1.1
113      */

114     public Object JavaDoc clone() {
115         try {
116             ZipEntry e = (ZipEntry) super.clone();
117
118             e.setName(getName());
119             e.setComment(getComment());
120             e.setMethod(getMethod());
121             e.setTime(getTime());
122             long size = getSize();
123             if (size > 0) {
124                 e.setSize(size);
125             }
126             long cSize = getCompressedSize();
127             if (cSize > 0) {
128                 e.setComprSize(cSize);
129             }
130             long crc = getCrc();
131             if (crc > 0) {
132                 e.setCrc(crc);
133             }
134
135             e.extraFields = (Vector JavaDoc) extraFields.clone();
136             e.setInternalAttributes(getInternalAttributes());
137             e.setExternalAttributes(getExternalAttributes());
138             e.setExtraFields(getExtraFields());
139             return e;
140         } catch (Throwable JavaDoc t) {
141             // in JDK 1.1 ZipEntry is not Cloneable, so super.clone declares
142
// to throw CloneNotSupported - since JDK 1.2 it is overridden to
143
// not throw that exception
144
return null;
145         }
146     }
147
148     /**
149      * Retrieves the internal file attributes.
150      *
151      * @since 1.1
152      */

153     public int getInternalAttributes() {
154         return internalAttributes;
155     }
156
157     /**
158      * Sets the internal file attributes.
159      *
160      * @since 1.1
161      */

162     public void setInternalAttributes(int value) {
163         internalAttributes = value;
164     }
165
166     /**
167      * Retrieves the external file attributes.
168      *
169      * @since 1.1
170      */

171     public long getExternalAttributes() {
172         return externalAttributes;
173     }
174
175     /**
176      * Sets the external file attributes.
177      *
178      * @since 1.1
179      */

180     public void setExternalAttributes(long value) {
181         externalAttributes = value;
182     }
183
184     /**
185      * Sets Unix permissions in a way that is understood by Info-Zip's
186      * unzip command.
187      *
188      * @since Ant 1.5.2
189      */

190     public void setUnixMode(int mode) {
191         setExternalAttributes((mode << 16)
192                               // MS-DOS read-only attribute
193
| ((mode & 0200) == 0 ? 1 : 0)
194                               // MS-DOS directory flag
195
| (isDirectory() ? 0x10 : 0));
196         platform = PLATFORM_UNIX;
197     }
198
199     /**
200      * Unix permission.
201      *
202      * @since Ant 1.6
203      */

204     public int getUnixMode() {
205         return (int) ((getExternalAttributes() >> 16) & 0xFFFF);
206     }
207
208     /**
209      * Platform specification to put into the &quot;version made
210      * by&quot; part of the central file header.
211      *
212      * @return 0 (MS-DOS FAT) unless {@link #setUnixMode setUnixMode}
213      * has been called, in which case 3 (Unix) will be returned.
214      *
215      * @since Ant 1.5.2
216      */

217     public int getPlatform() {
218         return platform;
219     }
220
221     /**
222      * @since 1.9
223      */

224     protected void setPlatform(int platform) {
225         this.platform = platform;
226     }
227
228     /**
229      * Replaces all currently attached extra fields with the new array.
230      *
231      * @since 1.1
232      */

233     public void setExtraFields(ZipExtraField[] fields) {
234         extraFields.removeAllElements();
235         for (int i = 0; i < fields.length; i++) {
236             extraFields.addElement(fields[i]);
237         }
238         setExtra();
239     }
240
241     /**
242      * Retrieves extra fields.
243      *
244      * @since 1.1
245      */

246     public ZipExtraField[] getExtraFields() {
247         ZipExtraField[] result = new ZipExtraField[extraFields.size()];
248         extraFields.copyInto(result);
249         return result;
250     }
251
252     /**
253      * Adds an extra fields - replacing an already present extra field
254      * of the same type.
255      *
256      * @since 1.1
257      */

258     public void addExtraField(ZipExtraField ze) {
259         ZipShort type = ze.getHeaderId();
260         boolean done = false;
261         for (int i = 0; !done && i < extraFields.size(); i++) {
262             if (((ZipExtraField) extraFields.elementAt(i)).getHeaderId().equals(type)) {
263                 extraFields.setElementAt(ze, i);
264                 done = true;
265             }
266         }
267         if (!done) {
268             extraFields.addElement(ze);
269         }
270         setExtra();
271     }
272
273     /**
274      * Remove an extra fields.
275      *
276      * @since 1.1
277      */

278     public void removeExtraField(ZipShort type) {
279         boolean done = false;
280         for (int i = 0; !done && i < extraFields.size(); i++) {
281             if (((ZipExtraField) extraFields.elementAt(i)).getHeaderId().equals(type)) {
282                 extraFields.removeElementAt(i);
283                 done = true;
284             }
285         }
286         if (!done) {
287             throw new java.util.NoSuchElementException JavaDoc();
288         }
289         setExtra();
290     }
291
292     /**
293      * Throws an Exception if extra data cannot be parsed into extra fields.
294      *
295      * @since 1.1
296      */

297     public void setExtra(byte[] extra) throws RuntimeException JavaDoc {
298         try {
299             setExtraFields(ExtraFieldUtils.parse(extra));
300         } catch (Exception JavaDoc e) {
301             throw new RuntimeException JavaDoc(e.getMessage());
302         }
303     }
304
305     /**
306      * Unfortunately {@link java.util.zip.ZipOutputStream
307      * java.util.zip.ZipOutputStream} seems to access the extra data
308      * directly, so overriding getExtra doesn't help - we need to
309      * modify super's data directly.
310      *
311      * @since 1.1
312      */

313     protected void setExtra() {
314         super.setExtra(ExtraFieldUtils.mergeLocalFileDataData(getExtraFields()));
315     }
316
317     /**
318      * Retrieves the extra data for the local file data.
319      *
320      * @since 1.1
321      */

322     public byte[] getLocalFileDataExtra() {
323         byte[] extra = getExtra();
324         return extra != null ? extra : new byte[0];
325     }
326
327     /**
328      * Retrieves the extra data for the central directory.
329      *
330      * @since 1.1
331      */

332     public byte[] getCentralDirectoryExtra() {
333         return ExtraFieldUtils.mergeCentralDirectoryData(getExtraFields());
334     }
335
336     /**
337      * Helper for JDK 1.1 <-> 1.2 incompatibility.
338      *
339      * @since 1.2
340      */

341     private Long JavaDoc compressedSize = null;
342
343     /**
344      * Make this class work in JDK 1.1 like a 1.2 class.
345      *
346      * <p>This either stores the size for later usage or invokes
347      * setCompressedSize via reflection.</p>
348      *
349      * @since 1.2
350      */

351     public void setComprSize(long size) {
352         if (haveSetCompressedSize()) {
353             performSetCompressedSize(this, size);
354         } else {
355             compressedSize = new Long JavaDoc(size);
356         }
357     }
358
359     /**
360      * Override to make this class work in JDK 1.1 like a 1.2 class.
361      *
362      * @since 1.2
363      */

364     public long getCompressedSize() {
365         if (compressedSize != null) {
366             // has been set explicitly and we are running in a 1.1 VM
367
return compressedSize.longValue();
368         }
369         return super.getCompressedSize();
370     }
371
372     /**
373      * @since 1.9
374      */

375     public String JavaDoc getName() {
376         return name == null ? super.getName() : name;
377     }
378
379     /**
380      * @since 1.10
381      */

382     public boolean isDirectory() {
383         return getName().endsWith("/");
384     }
385
386     protected void setName(String JavaDoc name) {
387         this.name = name;
388     }
389
390     /**
391      * Helper for JDK 1.1
392      *
393      * @since 1.2
394      */

395     private static Method JavaDoc setCompressedSizeMethod = null;
396     /**
397      * Helper for JDK 1.1
398      *
399      * @since 1.2
400      */

401     private static Object JavaDoc lockReflection = new Object JavaDoc();
402     /**
403      * Helper for JDK 1.1
404      *
405      * @since 1.2
406      */

407     private static boolean triedToGetMethod = false;
408
409     /**
410      * Are we running JDK 1.2 or higher?
411      *
412      * @since 1.2
413      */

414     private static boolean haveSetCompressedSize() {
415         checkSCS();
416         return setCompressedSizeMethod != null;
417     }
418
419     /**
420      * Invoke setCompressedSize via reflection.
421      *
422      * @since 1.2
423      */

424     private static void performSetCompressedSize(ZipEntry ze, long size) {
425         Long JavaDoc[] s = {new Long JavaDoc(size)};
426         try {
427             setCompressedSizeMethod.invoke(ze, s);
428         } catch (InvocationTargetException JavaDoc ite) {
429             Throwable JavaDoc nested = ite.getTargetException();
430             throw new RuntimeException JavaDoc("Exception setting the compressed size "
431                                        + "of " + ze + ": "
432                                        + nested.getMessage());
433         } catch (Throwable JavaDoc other) {
434             throw new RuntimeException JavaDoc("Exception setting the compressed size "
435                                        + "of " + ze + ": "
436                                        + other.getMessage());
437         }
438     }
439
440     /**
441      * Try to get a handle to the setCompressedSize method.
442      *
443      * @since 1.2
444      */

445     private static void checkSCS() {
446         if (!triedToGetMethod) {
447             synchronized (lockReflection) {
448                 triedToGetMethod = true;
449                 try {
450                     setCompressedSizeMethod =
451                         java.util.zip.ZipEntry JavaDoc.class.getMethod("setCompressedSize",
452                                                                new Class JavaDoc[] {Long.TYPE});
453                 } catch (NoSuchMethodException JavaDoc nse) {
454                 }
455             }
456         }
457     }
458
459 }
460
Popular Tags