jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java
changeset 16905 0419f45c7761
parent 14327 c0d86f6f8be8
child 25186 63e1a2ec30f5
--- a/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java	Tue Apr 16 21:04:33 2013 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java	Wed Apr 17 10:15:33 2013 +0800
@@ -30,18 +30,20 @@
 
 package sun.security.krb5.internal;
 
-import java.util.TimeZone;
-import sun.security.util.*;
+import sun.security.krb5.Asn1Exception;
 import sun.security.krb5.Config;
 import sun.security.krb5.KrbException;
-import sun.security.krb5.Asn1Exception;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+
+import java.io.IOException;
+import java.util.Calendar;
 import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Calendar;
-import java.io.IOException;
+import java.util.TimeZone;
 
 /**
- * Implements the ASN.1 KerberosTime type.
+ * Implements the ASN.1 KerberosTime type. This is an immutable class.
  *
  * <xmp>
  * KerberosTime    ::= GeneralizedTime -- with no fractional seconds
@@ -62,55 +64,38 @@
  * same class can be used as a precise timestamp in Authenticator etc.
  */
 
-public class KerberosTime implements Cloneable {
+public class KerberosTime {
 
-    private long kerberosTime; // milliseconds since epoch, a Date.getTime() value
-    private int  microSeconds; // the last three digits of the microsecond value
+    private final long kerberosTime; // milliseconds since epoch, Date.getTime()
+    private final int  microSeconds; // last 3 digits of the real microsecond
 
     // The time when this class is loaded. Used in setNow()
     private static long initMilli = System.currentTimeMillis();
     private static long initMicro = System.nanoTime() / 1000;
 
-    private static long syncTime;
     private static boolean DEBUG = Krb5.DEBUG;
 
-    public static final boolean NOW = true;
-    public static final boolean UNADJUSTED_NOW = false;
-
-    public KerberosTime(long time) {
-        kerberosTime = time;
-    }
-
+    // Do not make this public. It's a little confusing that micro
+    // is only the last 3 digits of microsecond.
     private KerberosTime(long time, int micro) {
         kerberosTime = time;
         microSeconds = micro;
     }
 
-    public Object clone() {
-        return new KerberosTime(kerberosTime, microSeconds);
+    /**
+     * Creates a KerberosTime object from milliseconds since epoch.
+     */
+    public KerberosTime(long time) {
+        this(time, 0);
     }
 
     // This constructor is used in the native code
     // src/windows/native/sun/security/krb5/NativeCreds.c
     public KerberosTime(String time) throws Asn1Exception {
-        kerberosTime = toKerberosTime(time);
-    }
-
-    /**
-     * Constructs a KerberosTime object.
-     * @param encoding a DER-encoded data.
-     * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
-     * @exception IOException if an I/O error occurs while reading encoded data.
-     */
-    public KerberosTime(DerValue encoding) throws Asn1Exception, IOException {
-        GregorianCalendar calendar = new GregorianCalendar();
-        Date temp = encoding.getGeneralizedTime();
-        kerberosTime = temp.getTime();
+        this(toKerberosTime(time), 0);
     }
 
     private static long toKerberosTime(String time) throws Asn1Exception {
-        // this method only used by KerberosTime class.
-
         // ASN.1 GeneralizedTime format:
 
         // "19700101000000Z"
@@ -133,30 +118,34 @@
                      Integer.parseInt(time.substring(8, 10)),
                      Integer.parseInt(time.substring(10, 12)),
                      Integer.parseInt(time.substring(12, 14)));
+        return calendar.getTimeInMillis();
+    }
 
-        //The Date constructor assumes the setting are local relative
-        //and converts the time to UTC before storing it.  Since we
-        //want the internal representation to correspond to local
-        //and not UTC time we subtract the UTC time offset.
-        return (calendar.getTime().getTime());
-
+    /**
+     * Creates a KerberosTime object from a Date object.
+     */
+    public KerberosTime(Date time) {
+        this(time.getTime(), 0);
     }
 
-    // should be moved to sun.security.krb5.util class
-    public static String zeroPad(String s, int length) {
-        StringBuffer temp = new StringBuffer(s);
-        while (temp.length() < length)
-            temp.insert(0, '0');
-        return temp.toString();
-    }
-
-    public KerberosTime(Date time) {
-        kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
-    }
-
-    public KerberosTime(boolean initToNow) {
-        if (initToNow) {
-            setNow();
+    /**
+     * Creates a KerberosTime object for now. It uses System.nanoTime()
+     * to get a more precise time than "new Date()".
+     */
+    public static KerberosTime now() {
+        long newMilli = System.currentTimeMillis();
+        long newMicro = System.nanoTime() / 1000;
+        long microElapsed = newMicro - initMicro;
+        long calcMilli = initMilli + microElapsed/1000;
+        if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
+            if (DEBUG) {
+                System.out.println("System time adjusted");
+            }
+            initMilli = newMilli;
+            initMicro = newMicro;
+            return new KerberosTime(newMilli, 0);
+        } else {
+            return new KerberosTime(calcMilli, (int)(microElapsed % 1000));
         }
     }
 
@@ -169,13 +158,13 @@
         calendar.clear();
 
         calendar.setTimeInMillis(kerberosTime);
-        return zeroPad(Integer.toString(calendar.get(Calendar.YEAR)), 4) +
-            zeroPad(Integer.toString(calendar.get(Calendar.MONTH) + 1), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.HOUR_OF_DAY)), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.MINUTE)), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.SECOND)), 2) + 'Z';
-
+        return String.format("%04d%02d%02d%02d%02d%02dZ",
+                calendar.get(Calendar.YEAR),
+                calendar.get(Calendar.MONTH) + 1,
+                calendar.get(Calendar.DAY_OF_MONTH),
+                calendar.get(Calendar.HOUR_OF_DAY),
+                calendar.get(Calendar.MINUTE),
+                calendar.get(Calendar.SECOND));
     }
 
     /**
@@ -194,40 +183,8 @@
         return kerberosTime;
     }
 
-
-    public void setTime(Date time) {
-        kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
-        microSeconds = 0;
-    }
-
-    public void setTime(long time) {
-        kerberosTime = time;
-        microSeconds = 0;
-    }
-
     public Date toDate() {
-        Date temp = new Date(kerberosTime);
-        temp.setTime(temp.getTime());
-        return temp;
-    }
-
-    public void setNow() {
-        long newMilli = System.currentTimeMillis();
-        long newMicro = System.nanoTime() / 1000;
-        long microElapsed = newMicro - initMicro;
-        long calcMilli = initMilli + microElapsed/1000;
-        if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
-            if (DEBUG) {
-                System.out.println("System time adjusted");
-            }
-            initMilli = newMilli;
-            initMicro = newMicro;
-            setTime(newMilli);
-            microSeconds = 0;
-        } else {
-            setTime(calcMilli);
-            microSeconds = (int)(microElapsed % 1000);
-        }
+        return new Date(kerberosTime);
     }
 
     public int getMicroSeconds() {
@@ -235,45 +192,25 @@
         return temp_long.intValue() + microSeconds;
     }
 
-    public void setMicroSeconds(int usec) {
-        microSeconds = usec % 1000;
-        Integer temp_int = new Integer(usec);
-        long temp_long = temp_int.longValue() / 1000L;
-        kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
+    /**
+     * Returns a new KerberosTime object with the original seconds
+     * and the given microseconds.
+     */
+    public KerberosTime withMicroSeconds(int usec) {
+        return new KerberosTime(
+                kerberosTime - kerberosTime%1000L + usec/1000L,
+                usec%1000);
     }
 
-    public void setMicroSeconds(Integer usec) {
-        if (usec != null) {
-            microSeconds = usec.intValue() % 1000;
-            long temp_long = usec.longValue() / 1000L;
-            kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
-        }
-    }
-
-    public boolean inClockSkew(int clockSkew) {
-        KerberosTime now = new KerberosTime(KerberosTime.NOW);
-
-        if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
-            clockSkew * 1000L)
-            return false;
-        return true;
+    private boolean inClockSkew(int clockSkew) {
+        return java.lang.Math.abs(kerberosTime - System.currentTimeMillis())
+                <= clockSkew * 1000L;
     }
 
     public boolean inClockSkew() {
         return inClockSkew(getDefaultSkew());
     }
 
-    public boolean inClockSkew(int clockSkew, KerberosTime now) {
-        if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
-            clockSkew * 1000L)
-            return false;
-        return true;
-    }
-
-    public boolean inClockSkew(KerberosTime time) {
-        return inClockSkew(getDefaultSkew(), time);
-    }
-
     public boolean greaterThanWRTClockSkew(KerberosTime time, int clockSkew) {
         if ((kerberosTime - time.kerberosTime) > clockSkew * 1000L)
             return true;
@@ -317,24 +254,22 @@
         return temp_long.intValue();
     }
 
-    public void setSeconds(int sec) {
-        Integer temp_int = new Integer(sec);
-        kerberosTime = temp_int.longValue() * 1000L;
-    }
-
     /**
      * Parse (unmarshal) a kerberostime from a DER input stream.  This form
      * parsing might be used when expanding a value which is part of
      * a constructed sequence and uses explicitly tagged type.
      *
      * @exception Asn1Exception on error.
-     * @param data the Der input stream value, which contains one or more marshaled value.
+     * @param data the Der input stream value, which contains
+     *             one or more marshaled value.
      * @param explicitTag tag number.
      * @param optional indicates if this data field is optional
      * @return an instance of KerberosTime.
      *
      */
-    public static KerberosTime parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
+    public static KerberosTime parse(
+            DerInputStream data, byte explicitTag, boolean optional)
+            throws Asn1Exception, IOException {
         if ((optional) && (((byte)data.peekByte() & (byte)0x1F)!= explicitTag))
             return null;
         DerValue der = data.getDerValue();
@@ -343,7 +278,8 @@
         }
         else {
             DerValue subDer = der.getData().getDerValue();
-            return new KerberosTime(subDer);
+            Date temp = subDer.getGeneralizedTime();
+            return new KerberosTime(temp.getTime(), 0);
         }
     }