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