< prev index next >

src/java.base/share/classes/java/util/zip/ZipEntry.java

Print this page
rev 11478 : 8073497: Lazy conversion of ZipEntry time
Reviewed-by: sherman, plevart

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -39,11 +39,13 @@
  */
 public
 class ZipEntry implements ZipConstants, Cloneable {
 
     String name;        // entry name
-    long time = -1;     // last modification time
+    long xdostime = -1; // last modification time (in extended DOS time,
+                        // where milliseconds lost in conversion might
+                        // be encoded into the upper half)
     FileTime mtime;     // last modification time, from extra field data
     FileTime atime;     // last access time, from extra field data
     FileTime ctime;     // creation time, from extra field data
     long crc = -1;      // crc-32 of entry data
     long size = -1;     // uncompressed size of entry data

@@ -62,10 +64,32 @@
      * Compression method for compressed (deflated) entries.
      */
     public static final int DEFLATED = 8;
 
     /**
+     * DOS time constant for representing timestamps before 1980.
+     */
+    static final long DOSTIME_BEFORE_1980 = (1 << 21) | (1 << 16);
+
+    /**
+     * Approximately 128 years, in milliseconds (ignoring leap years etc).
+     *
+     * This establish an approximate high-bound value for DOS times in
+     * milliseconds since epoch, used to enable an efficient but
+     * sufficient bounds check to avoid generating extended last modified
+     * time entries.
+     *
+     * Calculating the exact number is locale dependent, would require loading
+     * TimeZone data eagerly, and would make little practical sense. Since DOS
+     * times theoretically go to 2107 - with compatibility not guaranteed
+     * after 2099 - setting this to a time that is before but near 2099
+     * should be sufficient.
+     */
+    private static final long UPPER_DOSTIME_BOUND =
+            128L * 365 * 24 * 60 * 60 * 1000;
+
+    /**
      * Creates a new zip entry with the specified name.
      *
      * @param  name
      *         The entry name
      *

@@ -91,11 +115,11 @@
      * @throws NullPointerException if the entry object is null
      */
     public ZipEntry(ZipEntry e) {
         Objects.requireNonNull(e, "entry");
         name = e.name;
-        time = e.time;
+        xdostime = e.xdostime;
         mtime = e.mtime;
         atime = e.atime;
         ctime = e.ctime;
         crc = e.crc;
         size = e.size;

@@ -135,12 +159,18 @@
      *
      * @see #getTime()
      * @see #getLastModifiedTime()
      */
     public void setTime(long time) {
-        this.time = time;
+        this.xdostime = javaToExtendedDosTime(time);
+        // Avoid setting the mtime field if time is in the valid
+        // range for a DOS time
+        if (xdostime != DOSTIME_BEFORE_1980 && time <= UPPER_DOSTIME_BOUND) {
         this.mtime = null;
+        } else {
+            this.mtime = FileTime.from(time, TimeUnit.MILLISECONDS);
+        }
     }
 
     /**
      * Returns the last modification time of the entry.
      *

@@ -156,11 +186,14 @@
      *
      * @see #setTime(long)
      * @see #setLastModifiedTime(FileTime)
      */
     public long getTime() {
-        return time;
+        if (mtime != null) {
+            return mtime.toMillis();
+        }
+        return (xdostime != -1) ? extendedDosToJavaTime(xdostime) : -1;
     }
 
     /**
      * Sets the last modification time of the entry.
      *

@@ -179,11 +212,11 @@
      * @see #getLastModifiedTime()
      * @since 1.8
      */
     public ZipEntry setLastModifiedTime(FileTime time) {
         this.mtime = Objects.requireNonNull(time, "lastModifiedTime");
-        this.time = time.to(TimeUnit.MILLISECONDS);
+        this.xdostime = javaToExtendedDosTime(time.to(TimeUnit.MILLISECONDS));
         return this;
     }
 
     /**
      * Returns the last modification time of the entry.

@@ -202,13 +235,13 @@
      * @since 1.8
      */
     public FileTime getLastModifiedTime() {
         if (mtime != null)
             return mtime;
-        if (time == -1)
+        if (xdostime == -1)
             return null;
-        return FileTime.from(time, TimeUnit.MILLISECONDS);
+        return FileTime.from(getTime(), TimeUnit.MILLISECONDS);
     }
 
     /**
      * Sets the last access time of the entry.
      *
< prev index next >