emul/mini/src/main/java/java/util/zip/ZipEntry.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
parent 609 48ef38e9677e
permissions -rw-r--r--
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
     1 /*
     2  * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.util.zip;
    27 
    28 /**
    29  * This class is used to represent a ZIP file entry.
    30  *
    31  * @author      David Connelly
    32  */
    33 public
    34 class ZipEntry implements ZipConstants, Cloneable {
    35     String name;        // entry name
    36     long time = -1;     // modification time (in DOS time)
    37     long crc = -1;      // crc-32 of entry data
    38     long size = -1;     // uncompressed size of entry data
    39     long csize = -1;    // compressed size of entry data
    40     int method = -1;    // compression method
    41     int flag = 0;       // general purpose flag
    42     byte[] extra;       // optional extra field data for entry
    43     String comment;     // optional comment string for entry
    44 
    45     /**
    46      * Compression method for uncompressed entries.
    47      */
    48     public static final int STORED = 0;
    49 
    50     /**
    51      * Compression method for compressed (deflated) entries.
    52      */
    53     public static final int DEFLATED = 8;
    54 
    55     /**
    56      * Creates a new zip entry with the specified name.
    57      *
    58      * @param name the entry name
    59      * @exception NullPointerException if the entry name is null
    60      * @exception IllegalArgumentException if the entry name is longer than
    61      *            0xFFFF bytes
    62      */
    63     public ZipEntry(String name) {
    64         if (name == null) {
    65             throw new NullPointerException();
    66         }
    67         if (name.length() > 0xFFFF) {
    68             throw new IllegalArgumentException("entry name too long");
    69         }
    70         this.name = name;
    71     }
    72 
    73     /**
    74      * Creates a new zip entry with fields taken from the specified
    75      * zip entry.
    76      * @param e a zip Entry object
    77      */
    78     public ZipEntry(ZipEntry e) {
    79         name = e.name;
    80         time = e.time;
    81         crc = e.crc;
    82         size = e.size;
    83         csize = e.csize;
    84         method = e.method;
    85         flag = e.flag;
    86         extra = e.extra;
    87         comment = e.comment;
    88     }
    89 
    90     /*
    91      * Creates a new un-initialized zip entry
    92      */
    93     ZipEntry() {}
    94 
    95     /**
    96      * Returns the name of the entry.
    97      * @return the name of the entry
    98      */
    99     public String getName() {
   100         return name;
   101     }
   102 
   103     /**
   104      * Sets the modification time of the entry.
   105      * @param time the entry modification time in number of milliseconds
   106      *             since the epoch
   107      * @see #getTime()
   108      */
   109     public void setTime(long time) {
   110         this.time = javaToDosTime(time);
   111     }
   112 
   113     /**
   114      * Returns the modification time of the entry, or -1 if not specified.
   115      * @return the modification time of the entry, or -1 if not specified
   116      * @see #setTime(long)
   117      */
   118     public long getTime() {
   119         return time != -1 ? dosToJavaTime(time) : -1;
   120     }
   121 
   122     /**
   123      * Sets the uncompressed size of the entry data.
   124      * @param size the uncompressed size in bytes
   125      * @exception IllegalArgumentException if the specified size is less
   126      *            than 0, is greater than 0xFFFFFFFF when
   127      *            <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
   128      *            or is less than 0 when ZIP64 is supported
   129      * @see #getSize()
   130      */
   131     public void setSize(long size) {
   132         if (size < 0) {
   133             throw new IllegalArgumentException("invalid entry size");
   134         }
   135         this.size = size;
   136     }
   137 
   138     /**
   139      * Returns the uncompressed size of the entry data, or -1 if not known.
   140      * @return the uncompressed size of the entry data, or -1 if not known
   141      * @see #setSize(long)
   142      */
   143     public long getSize() {
   144         return size;
   145     }
   146 
   147     /**
   148      * Returns the size of the compressed entry data, or -1 if not known.
   149      * In the case of a stored entry, the compressed size will be the same
   150      * as the uncompressed size of the entry.
   151      * @return the size of the compressed entry data, or -1 if not known
   152      * @see #setCompressedSize(long)
   153      */
   154     public long getCompressedSize() {
   155         return csize;
   156     }
   157 
   158     /**
   159      * Sets the size of the compressed entry data.
   160      * @param csize the compressed size to set to
   161      * @see #getCompressedSize()
   162      */
   163     public void setCompressedSize(long csize) {
   164         this.csize = csize;
   165     }
   166 
   167     /**
   168      * Sets the CRC-32 checksum of the uncompressed entry data.
   169      * @param crc the CRC-32 value
   170      * @exception IllegalArgumentException if the specified CRC-32 value is
   171      *            less than 0 or greater than 0xFFFFFFFF
   172      * @see #getCrc()
   173      */
   174     public void setCrc(long crc) {
   175         if (crc < 0 || crc > 0xFFFFFFFFL) {
   176             throw new IllegalArgumentException("invalid entry crc-32");
   177         }
   178         this.crc = crc;
   179     }
   180 
   181     /**
   182      * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
   183      * not known.
   184      * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
   185      * not known
   186      * @see #setCrc(long)
   187      */
   188     public long getCrc() {
   189         return crc;
   190     }
   191 
   192     /**
   193      * Sets the compression method for the entry.
   194      * @param method the compression method, either STORED or DEFLATED
   195      * @exception IllegalArgumentException if the specified compression
   196      *            method is invalid
   197      * @see #getMethod()
   198      */
   199     public void setMethod(int method) {
   200         if (method != STORED && method != DEFLATED) {
   201             throw new IllegalArgumentException("invalid compression method");
   202         }
   203         this.method = method;
   204     }
   205 
   206     /**
   207      * Returns the compression method of the entry, or -1 if not specified.
   208      * @return the compression method of the entry, or -1 if not specified
   209      * @see #setMethod(int)
   210      */
   211     public int getMethod() {
   212         return method;
   213     }
   214 
   215     /**
   216      * Sets the optional extra field data for the entry.
   217      * @param extra the extra field data bytes
   218      * @exception IllegalArgumentException if the length of the specified
   219      *            extra field data is greater than 0xFFFF bytes
   220      * @see #getExtra()
   221      */
   222     public void setExtra(byte[] extra) {
   223         if (extra != null && extra.length > 0xFFFF) {
   224             throw new IllegalArgumentException("invalid extra field length");
   225         }
   226         this.extra = extra;
   227     }
   228 
   229     /**
   230      * Returns the extra field data for the entry, or null if none.
   231      * @return the extra field data for the entry, or null if none
   232      * @see #setExtra(byte[])
   233      */
   234     public byte[] getExtra() {
   235         return extra;
   236     }
   237 
   238     /**
   239      * Sets the optional comment string for the entry.
   240      *
   241      * <p>ZIP entry comments have maximum length of 0xffff. If the length of the
   242      * specified comment string is greater than 0xFFFF bytes after encoding, only
   243      * the first 0xFFFF bytes are output to the ZIP file entry.
   244      *
   245      * @param comment the comment string
   246      *
   247      * @see #getComment()
   248      */
   249     public void setComment(String comment) {
   250         this.comment = comment;
   251     }
   252 
   253     /**
   254      * Returns the comment string for the entry, or null if none.
   255      * @return the comment string for the entry, or null if none
   256      * @see #setComment(String)
   257      */
   258     public String getComment() {
   259         return comment;
   260     }
   261 
   262     /**
   263      * Returns true if this is a directory entry. A directory entry is
   264      * defined to be one whose name ends with a '/'.
   265      * @return true if this is a directory entry
   266      */
   267     public boolean isDirectory() {
   268         return name.endsWith("/");
   269     }
   270 
   271     /**
   272      * Returns a string representation of the ZIP entry.
   273      */
   274     public String toString() {
   275         return getName();
   276     }
   277 
   278     /*
   279      * Converts DOS time to Java time (number of milliseconds since epoch).
   280      */
   281     private static long dosToJavaTime(long dtime) {
   282         return dtime;
   283         /* XXX:
   284         Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
   285                           (int)(((dtime >> 21) & 0x0f) - 1),
   286                           (int)((dtime >> 16) & 0x1f),
   287                           (int)((dtime >> 11) & 0x1f),
   288                           (int)((dtime >> 5) & 0x3f),
   289                           (int)((dtime << 1) & 0x3e));
   290         return d.getTime();
   291         */
   292     }
   293 
   294     /*
   295      * Converts Java time to DOS time.
   296      */
   297     private static long javaToDosTime(long time) {
   298         return time;
   299         /* XXX:
   300         Date d = new Date(time);
   301         int year = d.getYear() + 1900;
   302         if (year < 1980) {
   303             return (1 << 21) | (1 << 16);
   304         }
   305         return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
   306                d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
   307                d.getSeconds() >> 1;
   308         */
   309     }
   310 
   311     /**
   312      * Returns the hash code value for this entry.
   313      */
   314     public int hashCode() {
   315         return name.hashCode();
   316     }
   317 
   318     /**
   319      * Returns a copy of this entry.
   320      */
   321     public Object clone() {
   322         try {
   323             ZipEntry e = (ZipEntry)super.clone();
   324             e.extra = (extra == null) ? null : extra.clone();
   325             return e;
   326         } catch (CloneNotSupportedException e) {
   327             // This should never happen, since we are Cloneable
   328             throw new IllegalStateException();
   329         }
   330     }
   331 }