[multiple changes]
authorMark Wielaard <mark@gcc.gnu.org>
Sat, 25 Sep 2004 22:21:51 +0000 (22:21 +0000)
committerMark Wielaard <mark@gcc.gnu.org>
Sat, 25 Sep 2004 22:21:51 +0000 (22:21 +0000)
2004-09-25  Mark Wielaard  <mark@klomp.org>

        * Makefile.am (core_java_source_files): Add VMTimeZone.java.
        (nat_source_files): Rename natTimeZone.cc to natVMTimeZone.cc.
        * Makefile.in: Regenerated.

        * gcj/javaprims.h: Regenerated.

        * java/util/TimeZone.java (defaultZone): Use VMTimeZone.
        (getDefaultTimeZone): Make package private. Check that GMToffset
        contains at least one digit.
        (getDefaultTimeZoneId, readTimeZoneFile, readtzFile): (Re)Moved to
        VMTimeZone.
        * util/VMTimeZone.java: New file with above methods.

        * java/util/natTimeZone.cc: Removed (renamed).
        * java/util/natVMTimeZone.cc: Added (renamed).

2004-09-25  Jeroen Frijters  <jeroen@frijters.net>

        * java/util/TimeZone.java
        (getDefaultTimeZone): Fixed test to distinguish between hours and
        minutes in specified timezone.

From-SVN: r88112

libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/gcj/javaprims.h
libjava/java/util/TimeZone.java
libjava/java/util/VMTimeZone.java [new file with mode: 0644]
libjava/java/util/natTimeZone.cc [deleted file]
libjava/java/util/natVMTimeZone.cc [new file with mode: 0644]

index dd323d30e828a2a00b92f84c8fea6abf89e6f88d..4e1c6879907555aeff54b52e6c2b5b36d0b5672d 100644 (file)
@@ -1,3 +1,27 @@
+2004-09-25  Mark Wielaard  <mark@klomp.org>
+
+       * Makefile.am (core_java_source_files): Add VMTimeZone.java.
+       (nat_source_files): Rename natTimeZone.cc to natVMTimeZone.cc.
+       * Makefile.in: Regenerated.
+
+       * gcj/javaprims.h: Regenerated.
+
+       * java/util/TimeZone.java (defaultZone): Use VMTimeZone.
+       (getDefaultTimeZone): Make package private. Check that GMToffset
+       contains at least one digit.
+       (getDefaultTimeZoneId, readTimeZoneFile, readtzFile): (Re)Moved to
+       VMTimeZone.
+       * util/VMTimeZone.java: New file with above methods.
+
+       * java/util/natTimeZone.cc: Removed (renamed).
+       * java/util/natVMTimeZone.cc: Added (renamed).
+
+2004-09-25  Jeroen Frijters  <jeroen@frijters.net>
+
+       * java/util/TimeZone.java
+       (getDefaultTimeZone): Fixed test to distinguish between hours and
+       minutes in specified timezone.
+
 2004-09-25  Jeroen Frijters  <jeroen@frijters.net>
 
        * java/lang/reflect/Proxy.java (getPackage, ClassFactory): Fixed
index b126ab2c2560c9564866f811bb0693f4949796b2..543b48879f5922b8fc55a0482e3b8d3a689a18f4 100644 (file)
@@ -2424,6 +2424,7 @@ java/util/TreeMap.java \
 java/util/TreeSet.java \
 java/util/TooManyListenersException.java \
 java/util/Vector.java \
+java/util/VMTimeZone.java      \
 java/util/WeakHashMap.java \
 java/util/logging/ConsoleHandler.java \
 java/util/logging/ErrorManager.java \
@@ -3191,7 +3192,7 @@ java/nio/channels/natChannels.cc \
 java/nio/natDirectByteBufferImpl.cc \
 java/text/natCollator.cc \
 java/util/natResourceBundle.cc \
-java/util/natTimeZone.cc \
+java/util/natVMTimeZone.cc \
 java/util/zip/natDeflater.cc \
 java/util/zip/natInflater.cc
 
index 083bf097ce2f87f04215feec2b7e84d0a9dfab23..bd831fea3e598d591f0219783b868a20b952d2dd 100644 (file)
@@ -410,7 +410,7 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \
        java/lang/reflect/natProxy.cc java/net/natNetworkInterface.cc \
        java/net/natInetAddress.cc java/nio/channels/natChannels.cc \
        java/nio/natDirectByteBufferImpl.cc java/text/natCollator.cc \
-       java/util/natResourceBundle.cc java/util/natTimeZone.cc \
+       java/util/natResourceBundle.cc java/util/natVMTimeZone.cc \
        java/util/zip/natDeflater.cc java/util/zip/natInflater.cc \
        java/lang/dtoa.c java/lang/k_rem_pio2.c java/lang/s_tan.c \
        java/lang/e_acos.c java/lang/k_sin.c java/lang/strtod.c \
@@ -562,7 +562,7 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \
        java/util/TimerTask.java java/util/TreeMap.java \
        java/util/TreeSet.java \
        java/util/TooManyListenersException.java java/util/Vector.java \
-       java/util/WeakHashMap.java \
+       java/util/VMTimeZone.java java/util/WeakHashMap.java \
        java/util/logging/ConsoleHandler.java \
        java/util/logging/ErrorManager.java \
        java/util/logging/FileHandler.java \
@@ -2299,7 +2299,7 @@ am__objects_6 = gnu/gcj/natCore.lo \
        java/lang/reflect/natProxy.lo java/net/natNetworkInterface.lo \
        java/net/natInetAddress.lo java/nio/channels/natChannels.lo \
        java/nio/natDirectByteBufferImpl.lo java/text/natCollator.lo \
-       java/util/natResourceBundle.lo java/util/natTimeZone.lo \
+       java/util/natResourceBundle.lo java/util/natVMTimeZone.lo \
        java/util/zip/natDeflater.lo java/util/zip/natInflater.lo
 am__objects_7 = java/lang/dtoa.lo java/lang/k_rem_pio2.lo \
        java/lang/s_tan.lo java/lang/e_acos.lo java/lang/k_sin.lo \
@@ -2440,8 +2440,8 @@ am__objects_9 = java/lang/AbstractMethodError.lo \
        java/util/TimeZone.lo java/util/Timer.lo \
        java/util/TimerTask.lo java/util/TreeMap.lo \
        java/util/TreeSet.lo java/util/TooManyListenersException.lo \
-       java/util/Vector.lo java/util/WeakHashMap.lo \
-       java/util/logging/ConsoleHandler.lo \
+       java/util/Vector.lo java/util/VMTimeZone.lo \
+       java/util/WeakHashMap.lo java/util/logging/ConsoleHandler.lo \
        java/util/logging/ErrorManager.lo \
        java/util/logging/FileHandler.lo java/util/logging/Filter.lo \
        java/util/logging/Formatter.lo java/util/logging/Handler.lo \
@@ -6235,6 +6235,7 @@ java/util/TreeMap.java \
 java/util/TreeSet.java \
 java/util/TooManyListenersException.java \
 java/util/Vector.java \
+java/util/VMTimeZone.java      \
 java/util/WeakHashMap.java \
 java/util/logging/ConsoleHandler.java \
 java/util/logging/ErrorManager.java \
@@ -6991,7 +6992,7 @@ java/nio/channels/natChannels.cc \
 java/nio/natDirectByteBufferImpl.cc \
 java/text/natCollator.cc \
 java/util/natResourceBundle.cc \
-java/util/natTimeZone.cc \
+java/util/natVMTimeZone.cc \
 java/util/zip/natDeflater.cc \
 java/util/zip/natInflater.cc
 
@@ -8012,7 +8013,7 @@ java/util/$(DEPDIR)/$(am__dirstamp):
        @: > java/util/$(DEPDIR)/$(am__dirstamp)
 java/util/natResourceBundle.lo: java/util/$(am__dirstamp) \
        java/util/$(DEPDIR)/$(am__dirstamp)
-java/util/natTimeZone.lo: java/util/$(am__dirstamp) \
+java/util/natVMTimeZone.lo: java/util/$(am__dirstamp) \
        java/util/$(DEPDIR)/$(am__dirstamp)
 java/util/zip/$(am__dirstamp):
        @$(mkdir_p) java/util/zip
@@ -8536,6 +8537,8 @@ java/util/TooManyListenersException.lo: java/util/$(am__dirstamp) \
        java/util/$(DEPDIR)/$(am__dirstamp)
 java/util/Vector.lo: java/util/$(am__dirstamp) \
        java/util/$(DEPDIR)/$(am__dirstamp)
+java/util/VMTimeZone.lo: java/util/$(am__dirstamp) \
+       java/util/$(DEPDIR)/$(am__dirstamp)
 java/util/WeakHashMap.lo: java/util/$(am__dirstamp) \
        java/util/$(DEPDIR)/$(am__dirstamp)
 java/util/logging/$(am__dirstamp):
@@ -17139,6 +17142,8 @@ mostlyclean-compile:
        -rm -f java/util/TreeMap.lo
        -rm -f java/util/TreeSet.$(OBJEXT)
        -rm -f java/util/TreeSet.lo
+       -rm -f java/util/VMTimeZone.$(OBJEXT)
+       -rm -f java/util/VMTimeZone.lo
        -rm -f java/util/Vector.$(OBJEXT)
        -rm -f java/util/Vector.lo
        -rm -f java/util/WeakHashMap.$(OBJEXT)
@@ -17191,8 +17196,8 @@ mostlyclean-compile:
        -rm -f java/util/logging/XMLFormatter.lo
        -rm -f java/util/natResourceBundle.$(OBJEXT)
        -rm -f java/util/natResourceBundle.lo
-       -rm -f java/util/natTimeZone.$(OBJEXT)
-       -rm -f java/util/natTimeZone.lo
+       -rm -f java/util/natVMTimeZone.$(OBJEXT)
+       -rm -f java/util/natVMTimeZone.lo
        -rm -f java/util/prefs/AbstractPreferences.$(OBJEXT)
        -rm -f java/util/prefs/AbstractPreferences.lo
        -rm -f java/util/prefs/BackingStoreException.$(OBJEXT)
@@ -20538,10 +20543,11 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/TooManyListenersException.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/TreeMap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/TreeSet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/VMTimeZone.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/Vector.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/WeakHashMap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natResourceBundle.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natTimeZone.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natVMTimeZone.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/jar/$(DEPDIR)/Attributes.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/jar/$(DEPDIR)/JarEntry.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/util/jar/$(DEPDIR)/JarException.Plo@am__quote@
index 8b2b090b95c33d81e339fbd4b8603f89da0e600c..3120184650fd1033f7c9077b8554191a8142e3fe 100644 (file)
@@ -151,6 +151,7 @@ extern "Java"
       class Comparable;
       class Compiler;
       class ConcreteProcess;
+      class ConcreteProcess$EOFInputStream;
       class ConcreteProcess$ProcessManager;
       class Double;
       class Error;
@@ -359,6 +360,7 @@ extern "Java"
       class TreeMap$SubMap;
       class TreeMap$TreeIterator;
       class TreeSet;
+      class VMTimeZone;
       class Vector;
       class WeakHashMap;
       class WeakHashMap$WeakBucket;
index cc3c7a3d283314c782aef3f08ea23b1bba834a23..1e06e535611bc12ec2ce1b6ec036c90d39ffbbdd 100644 (file)
@@ -38,9 +38,7 @@ exception statement from your version. */
 
 
 package java.util;
-import gnu.classpath.Configuration;
 
-import java.io.*;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.text.DateFormatSymbols;
@@ -90,14 +88,9 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
   /**
    * Tries to get the default TimeZone for this system if not already
    * set.  It will call <code>getDefaultTimeZone(String)</code> with
-   * the result of
-   * <code>System.getProperty("user.timezone")</code>,
-   * <code>System.getenv("TZ")</code>,
-   * <code>readTimeZoneFile("/etc/timezone")</code>,
-   * <code>readtzFile("/etc/localtime")</code> and
-   * <code>getDefaultTimeZoneId()</code>
-   * till a supported TimeZone is found.
-   * If every method fails GMT is returned.
+   * the result of <code>System.getProperty("user.timezone")</code>.
+   * If that fails it calls <code>VMTimeZone.getDefaultTimeZoneId()</code>.
+   * If that also fails GMT is returned.
    */
   private static synchronized TimeZone defaultZone()
   {
@@ -109,11 +102,6 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
            {
              public Object run()
              {
-               if (Configuration.INIT_LOAD_LIBRARY)
-                 {
-                   System.loadLibrary("javautil");
-                 }
-               
                TimeZone zone = null;
                
                // Prefer System property user.timezone.
@@ -121,37 +109,9 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
                if (tzid != null && !tzid.equals(""))
                  zone = getDefaultTimeZone(tzid);
                
-               // See if TZ environment variable is set and accessible.
-               if (zone == null)
-                 {
-                   tzid = System.getenv("TZ");
-                   if (tzid != null && !tzid.equals(""))
-                     zone = getDefaultTimeZone(tzid);
-                 }
-               
-               // Try to parse /etc/timezone.
+               // Try platfom specific way.
                if (zone == null)
-                 {
-                   tzid = readTimeZoneFile("/etc/timezone");
-                   if (tzid != null && !tzid.equals(""))
-                     zone = getDefaultTimeZone(tzid);
-                 }
-               
-               // Try to parse /etc/localtime
-               if (zone == null)
-                 {
-                   tzid = readtzFile("/etc/localtime");
-                   if (tzid != null && !tzid.equals(""))
-                     zone = getDefaultTimeZone(tzid);
-                 }
-               
-               // Try some system specific way
-               if (zone == null)
-                 {
-                   tzid = getDefaultTimeZoneId();
-                   if (tzid != null && !tzid.equals(""))
-                     zone = getDefaultTimeZone(tzid);
-                 }
+                 zone = VMTimeZone.getDefaultTimeZoneId();
                
                // Fall back on GMT.
                if (zone == null)
@@ -842,238 +802,6 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
     return timezones0;
   }
 
-  /**
-   * This method returns a time zone id string which is in the form
-   * (standard zone name) or (standard zone name)(GMT offset) or
-   * (standard zone name)(GMT offset)(daylight time zone name).  The
-   * GMT offset can be in seconds, or where it is evenly divisible by
-   * 3600, then it can be in hours.  The offset must be the time to
-   * add to the local time to get GMT.  If a offset is given and the
-   * time zone observes daylight saving then the (daylight time zone
-   * name) must also be given (otherwise it is assumed the time zone
-   * does not observe any daylight savings).
-   * <p>
-   * The result of this method is given to getDefaultTimeZone(String)
-   * which tries to map the time zone id to a known TimeZone.  See
-   * that method on how the returned String is mapped to a real
-   * TimeZone object.
-   */
-  private static native String getDefaultTimeZoneId();
-
-  /**
-   * Tries to read the time zone name from a file. Only the first
-   * consecutive letters, digits, slashes, dashes and underscores are
-   * read from the file. If the file cannot be read or an IOException
-   * occurs null is returned.
-   * <p>
-   * The /etc/timezone file is not standard, but a lot of systems have
-   * it. If it exist the first line always contains a string
-   * describing the timezone of the host of domain. Some systems
-   * contain a /etc/TIMEZONE file which is used to set the TZ
-   * environment variable (which is checked before /etc/timezone is
-   * read).
-   */
-  private static String readTimeZoneFile(String file)
-  {
-    File f = new File(file);
-    if (!f.exists())
-      return null;
-
-    InputStreamReader isr = null;
-    try
-      {
-       FileInputStream fis = new FileInputStream(f);
-       BufferedInputStream bis = new BufferedInputStream(fis);
-       isr = new InputStreamReader(bis);
-       
-       StringBuffer sb = new StringBuffer();
-       int i = isr.read();
-       while (i != -1)
-         {
-           char c = (char) i;
-           if (Character.isLetter(c) || Character.isDigit(c)
-               || c == '/' || c == '-' || c == '_')
-             {
-               sb.append(c);
-               i = isr.read();
-             }
-           else
-             break;
-         }
-       return sb.toString();
-      }
-    catch (IOException ioe)
-      {
-       // Parse error, not a proper tzfile.
-       return null;
-      }
-    finally
-      {
-       try
-         {
-           if (isr != null)
-             isr.close();
-         }
-       catch (IOException ioe)
-         {
-           // Error while close, nothing we can do.
-         }
-      }
-  }
-
-  /**
-   * Tries to read a file as a "standard" tzfile and return a time
-   * zone id string as expected by <code>getDefaultTimeZone(String)</code>.
-   * If the file doesn't exist, an IOException occurs or it isn't a tzfile
-   * that can be parsed null is returned.
-   * <p>
-   * The tzfile structure (as also used by glibc) is described in the Olson
-   * tz database archive as can be found at
-   * <code>ftp://elsie.nci.nih.gov/pub/</code>.
-   * <p>
-   * At least the following platforms support the tzdata file format
-   * and /etc/localtime (GNU/Linux, Darwin, Solaris and FreeBSD at
-   * least). Some systems (like Darwin) don't start the file with the
-   * required magic bytes 'TZif', this implementation can handle
-   * that).
-   */
-  private static String readtzFile(String file)
-  {
-    File f = new File(file);
-    if (!f.exists())
-      return null;
-    
-    DataInputStream dis = null;
-    try
-      {
-        FileInputStream fis = new FileInputStream(f);
-        BufferedInputStream bis = new BufferedInputStream(fis);
-        dis = new DataInputStream(bis);
-       
-        // Make sure we are reading a tzfile.
-        byte[] tzif = new byte[4];
-        dis.readFully(tzif);
-        if (tzif[0] == 'T' && tzif[1] == 'Z'
-            && tzif[2] == 'i' && tzif[3] == 'f')
-         // Reserved bytes, ttisgmtcnt, ttisstdcnt and leapcnt
-         skipFully(dis, 16 + 3 * 4);
-       else
-         // Darwin has tzdata files that don't start with the TZif marker
-         skipFully(dis, 16 + 3 * 4 - 4);
-       
-       int timecnt = dis.readInt();
-       int typecnt = dis.readInt();
-       if (typecnt > 0)
-         {
-           int charcnt = dis.readInt();
-           // Transition times plus indexed transition times.
-           skipFully(dis, timecnt * (4 + 1));
-           
-           // Get last gmt_offset and dst/non-dst time zone names.
-           int abbrind = -1;
-           int dst_abbrind = -1;
-           int gmt_offset = 0;
-           while (typecnt-- > 0)
-             {
-               // gmtoff
-               int offset = dis.readInt();
-               int dst = dis.readByte();
-               if (dst == 0)
-                 {
-                   abbrind = dis.readByte();
-                   gmt_offset = offset;
-                 }
-               else
-                 dst_abbrind = dis.readByte();
-             }
-           
-           // gmt_offset is the offset you must add to UTC/GMT to
-           // get the local time, we need the offset to add to
-           // the local time to get UTC/GMT.
-           gmt_offset *= -1;
-           
-           // Turn into hours if possible.
-           if (gmt_offset % 3600 == 0)
-             gmt_offset /= 3600;
-           
-           if (abbrind >= 0)
-             {
-               byte[] names = new byte[charcnt];
-               dis.readFully(names);
-               int j = abbrind;
-               while (j < charcnt && names[j] != 0)
-                 j++;
-               
-               String zonename = new String(names, abbrind, j - abbrind,
-                                            "ASCII");
-               
-               String dst_zonename;
-               if (dst_abbrind >= 0)
-                 {
-                   j = dst_abbrind;
-                   while (j < charcnt && names[j] != 0)
-                     j++;
-                   dst_zonename = new String(names, dst_abbrind,
-                                             j - dst_abbrind, "ASCII");
-                 }
-               else
-                 dst_zonename = "";
-               
-               // Only use gmt offset when necessary.
-               // Also special case GMT+/- timezones.
-               String offset_string;
-               if ("".equals(dst_zonename)
-                   && (gmt_offset == 0
-                       || zonename.startsWith("GMT+")
-                       || zonename.startsWith("GMT-")))
-                 offset_string = "";
-               else
-                 offset_string = Integer.toString(gmt_offset);
-               
-               String id = zonename + offset_string + dst_zonename;
-               
-               return id;
-             }
-         }
-       
-       // Something didn't match while reading the file.
-       return null;
-      }
-    catch (IOException ioe)
-      {
-       // Parse error, not a proper tzfile.
-       return null;
-      }
-    finally
-      {
-       try
-         {
-           if (dis != null)
-             dis.close();
-         }
-       catch(IOException ioe)
-         {
-           // Error while close, nothing we can do.
-         }
-      }
-  }
-  
-  /**
-   * Skips the requested number of bytes in the given InputStream.
-   * Throws EOFException if not enough bytes could be skipped.
-   * Negative numbers of bytes to skip are ignored.
-   */
-  private static void skipFully(InputStream is, long l) throws IOException
-  {
-    while (l > 0)
-      {
-        long k = is.skip(l);
-        if (k <= 0)
-          throw new EOFException();
-        l -= k;
-      }
-  }
-  
   /**
    * Maps a time zone name (with optional GMT offset and daylight time
    * zone name) to one of the known time zones.  This method called
@@ -1111,7 +839,7 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
    * The standard time zone name for The Netherlands is "Europe/Amsterdam",
    * but can also be given as "CET-1CEST".
    */
-  private static TimeZone getDefaultTimeZone(String sysTimeZoneId)
+  static TimeZone getDefaultTimeZone(String sysTimeZoneId)
   {
     // First find start of GMT offset info and any Daylight zone name.
     int startGMToffset = 0;
@@ -1119,7 +847,11 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
     for (int i = 0; i < sysTimeZoneIdLength && startGMToffset == 0; i++)
       {
        char c = sysTimeZoneId.charAt(i);
-       if (c == '+' || c == '-' || Character.isDigit(c))
+       if (Character.isDigit(c))
+         startGMToffset = i;
+       else if ((c == '+' || c == '-')
+                && i + 1 < sysTimeZoneIdLength
+                && Character.isDigit(sysTimeZoneId.charAt(i + 1)))
          startGMToffset = i;
       }
     
@@ -1152,7 +884,7 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
        // Offset could be in hours or seconds.  Convert to millis.
        // The offset is given as the time to add to local time to get GMT
        // we need the time to add to GMT to get localtime.
-       if (gmtOffset < 24)
+       if (Math.abs(gmtOffset) < 24)
          gmtOffset *= 60 * 60;
        gmtOffset *= -1000;
       }
diff --git a/libjava/java/util/VMTimeZone.java b/libjava/java/util/VMTimeZone.java
new file mode 100644 (file)
index 0000000..77c055b
--- /dev/null
@@ -0,0 +1,345 @@
+/* java.util.VMTimeZone
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.Configuration;
+
+import java.io.*;
+
+/**
+ *
+ */
+final class VMTimeZone
+{
+  static
+  {
+    if (Configuration.INIT_LOAD_LIBRARY)
+      {
+       System.loadLibrary("javautil");
+      }
+  }
+               
+  /**
+   * This method returns a time zone id string which is in the form
+   * (standard zone name) or (standard zone name)(GMT offset) or
+   * (standard zone name)(GMT offset)(daylight time zone name).  The
+   * GMT offset can be in seconds, or where it is evenly divisible by
+   * 3600, then it can be in hours.  The offset must be the time to
+   * add to the local time to get GMT.  If a offset is given and the
+   * time zone observes daylight saving then the (daylight time zone
+   * name) must also be given (otherwise it is assumed the time zone
+   * does not observe any daylight savings).
+   * <p>
+   * The result of this method is given to the method
+   * TimeZone.getDefaultTimeZone(String) which tries to map the time
+   * zone id to a known TimeZone.  See that method on how the returned
+   * String is mapped to a real TimeZone object.
+   * <p>
+   * The reference implementation which is made for GNU/Posix like
+   * systems calls <code>System.getenv("TZ")</code>,
+   * <code>readTimeZoneFile("/etc/timezone")</code>,
+   * <code>readtzFile("/etc/localtime")</code> and finally
+   * <code>getSystemTimeZoneId()</code> till a supported TimeZone is
+   * found through <code>TimeZone.getDefaultTimeZone(String)</code>.
+   * If every method fails <code>null</code> is returned (which means
+   * the TimeZone code will fall back on GMT as default time zone).
+   * <p>
+   * Note that this method is called inside a
+   * <code>AccessController.doPrivileged()</code> block and runs with
+   * the priviliges of the java.util system classes.  It will only be
+   * called when the default time zone is not yet set, the system
+   * property user.timezone isn't set and it is requested for the
+   * first time.
+   */
+  static TimeZone getDefaultTimeZoneId()
+  {
+    TimeZone zone = null;
+
+    // See if TZ environment variable is set and accessible.
+    String tzid = System.getenv("TZ");
+    if (tzid != null && !tzid.equals(""))
+      zone = TimeZone.getDefaultTimeZone(tzid);
+
+    // Try to parse /etc/timezone.
+    if (zone == null)
+      {
+       tzid = readTimeZoneFile("/etc/timezone");
+       if (tzid != null && !tzid.equals(""))
+         zone = TimeZone.getDefaultTimeZone(tzid);
+      }
+    
+    // Try to parse /etc/localtime
+    if (zone == null)
+      {
+       tzid = readtzFile("/etc/localtime");
+       if (tzid != null && !tzid.equals(""))
+         zone = TimeZone.getDefaultTimeZone(tzid);
+      }
+
+    // Try some system specific way
+    if (zone == null)
+      {
+       tzid = getSystemTimeZoneId();
+       if (tzid != null && !tzid.equals(""))
+         zone = TimeZone.getDefaultTimeZone(tzid);
+      }
+
+    return zone;
+  }
+
+  /**
+   * Tries to read the time zone name from a file. Only the first
+   * consecutive letters, digits, slashes, dashes and underscores are
+   * read from the file. If the file cannot be read or an IOException
+   * occurs null is returned.
+   * <p>
+   * The /etc/timezone file is not standard, but a lot of systems have
+   * it. If it exist the first line always contains a string
+   * describing the timezone of the host of domain. Some systems
+   * contain a /etc/TIMEZONE file which is used to set the TZ
+   * environment variable (which is checked before /etc/timezone is
+   * read).
+   */
+  private static String readTimeZoneFile(String file)
+  {
+    File f = new File(file);
+    if (!f.exists())
+      return null;
+
+    InputStreamReader isr = null;
+    try
+      {
+       FileInputStream fis = new FileInputStream(f);
+       BufferedInputStream bis = new BufferedInputStream(fis);
+       isr = new InputStreamReader(bis);
+       
+       StringBuffer sb = new StringBuffer();
+       int i = isr.read();
+       while (i != -1)
+         {
+           char c = (char) i;
+           if (Character.isLetter(c) || Character.isDigit(c)
+               || c == '/' || c == '-' || c == '_')
+             {
+               sb.append(c);
+               i = isr.read();
+             }
+           else
+             break;
+         }
+       return sb.toString();
+      }
+    catch (IOException ioe)
+      {
+       // Parse error, not a proper tzfile.
+       return null;
+      }
+    finally
+      {
+       try
+         {
+           if (isr != null)
+             isr.close();
+         }
+       catch (IOException ioe)
+         {
+           // Error while close, nothing we can do.
+         }
+      }
+  }
+
+  /**
+   * Tries to read a file as a "standard" tzfile and return a time
+   * zone id string as expected by <code>getDefaultTimeZone(String)</code>.
+   * If the file doesn't exist, an IOException occurs or it isn't a tzfile
+   * that can be parsed null is returned.
+   * <p>
+   * The tzfile structure (as also used by glibc) is described in the Olson
+   * tz database archive as can be found at
+   * <code>ftp://elsie.nci.nih.gov/pub/</code>.
+   * <p>
+   * At least the following platforms support the tzdata file format
+   * and /etc/localtime (GNU/Linux, Darwin, Solaris and FreeBSD at
+   * least). Some systems (like Darwin) don't start the file with the
+   * required magic bytes 'TZif', this implementation can handle
+   * that).
+   */
+  private static String readtzFile(String file)
+  {
+    File f = new File(file);
+    if (!f.exists())
+      return null;
+    
+    DataInputStream dis = null;
+    try
+      {
+        FileInputStream fis = new FileInputStream(f);
+        BufferedInputStream bis = new BufferedInputStream(fis);
+        dis = new DataInputStream(bis);
+       
+        // Make sure we are reading a tzfile.
+        byte[] tzif = new byte[4];
+        dis.readFully(tzif);
+        if (tzif[0] == 'T' && tzif[1] == 'Z'
+            && tzif[2] == 'i' && tzif[3] == 'f')
+         // Reserved bytes, ttisgmtcnt, ttisstdcnt and leapcnt
+         skipFully(dis, 16 + 3 * 4);
+       else
+         // Darwin has tzdata files that don't start with the TZif marker
+         skipFully(dis, 16 + 3 * 4 - 4);
+       
+       int timecnt = dis.readInt();
+       int typecnt = dis.readInt();
+       if (typecnt > 0)
+         {
+           int charcnt = dis.readInt();
+           // Transition times plus indexed transition times.
+           skipFully(dis, timecnt * (4 + 1));
+           
+           // Get last gmt_offset and dst/non-dst time zone names.
+           int abbrind = -1;
+           int dst_abbrind = -1;
+           int gmt_offset = 0;
+           while (typecnt-- > 0)
+             {
+               // gmtoff
+               int offset = dis.readInt();
+               int dst = dis.readByte();
+               if (dst == 0)
+                 {
+                   abbrind = dis.readByte();
+                   gmt_offset = offset;
+                 }
+               else
+                 dst_abbrind = dis.readByte();
+             }
+           
+           // gmt_offset is the offset you must add to UTC/GMT to
+           // get the local time, we need the offset to add to
+           // the local time to get UTC/GMT.
+           gmt_offset *= -1;
+           
+           // Turn into hours if possible.
+           if (gmt_offset % 3600 == 0)
+             gmt_offset /= 3600;
+           
+           if (abbrind >= 0)
+             {
+               byte[] names = new byte[charcnt];
+               dis.readFully(names);
+               int j = abbrind;
+               while (j < charcnt && names[j] != 0)
+                 j++;
+               
+               String zonename = new String(names, abbrind, j - abbrind,
+                                            "ASCII");
+               
+               String dst_zonename;
+               if (dst_abbrind >= 0)
+                 {
+                   j = dst_abbrind;
+                   while (j < charcnt && names[j] != 0)
+                     j++;
+                   dst_zonename = new String(names, dst_abbrind,
+                                             j - dst_abbrind, "ASCII");
+                 }
+               else
+                 dst_zonename = "";
+               
+               // Only use gmt offset when necessary.
+               // Also special case GMT+/- timezones.
+               String offset_string;
+               if ("".equals(dst_zonename)
+                   && (gmt_offset == 0
+                       || zonename.startsWith("GMT+")
+                       || zonename.startsWith("GMT-")))
+                 offset_string = "";
+               else
+                 offset_string = Integer.toString(gmt_offset);
+               
+               String id = zonename + offset_string + dst_zonename;
+               
+               return id;
+             }
+         }
+       
+       // Something didn't match while reading the file.
+       return null;
+      }
+    catch (IOException ioe)
+      {
+       // Parse error, not a proper tzfile.
+       return null;
+      }
+    finally
+      {
+       try
+         {
+           if (dis != null)
+             dis.close();
+         }
+       catch(IOException ioe)
+         {
+           // Error while close, nothing we can do.
+         }
+      }
+  }
+  
+  /**
+   * Skips the requested number of bytes in the given InputStream.
+   * Throws EOFException if not enough bytes could be skipped.
+   * Negative numbers of bytes to skip are ignored.
+   */
+  private static void skipFully(InputStream is, long l) throws IOException
+  {
+    while (l > 0)
+      {
+        long k = is.skip(l);
+        if (k <= 0)
+          throw new EOFException();
+        l -= k;
+      }
+  }
+
+  /**
+   * Tries to get the system time zone id through native code.
+   */
+  private static native String getSystemTimeZoneId();
+}
diff --git a/libjava/java/util/natTimeZone.cc b/libjava/java/util/natTimeZone.cc
deleted file mode 100644 (file)
index c23d9e6..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-// natTimeZone.cc -- Native side of TimeZone class.
-
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation
-
-   This file is part of libgcj.
-
-This software is copyrighted work licensed under the terms of the
-Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
-details.  */
-
-#include <config.h>
-#include <platform.h>
-
-#include <gcj/cni.h>
-#include <jvm.h>
-
-#include <java/util/TimeZone.h>
-#include <java/lang/Character.h>
-#include <java/lang/Integer.h>
-
-#include <stdio.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-#  include <sys/time.h>
-# else
-#  include <time.h>
-# endif
-#endif
-
-#include <string.h>
-
-/**
- * This method returns a time zone id string which is in the form
- * (standard zone name) or (standard zone name)(GMT offset) or
- * (standard zone name)(GMT offset)(daylight time zone name).  The
- * GMT offset can be in seconds, or where it is evenly divisible by
- * 3600, then it can be in hours.  The offset must be the time to
- * add to the local time to get GMT.  If a offset is given and the
- * time zone observes daylight saving then the (daylight time zone
- * name) must also be given (otherwise it is assumed the time zone
- * does not observe any daylight savings).
- * <p>
- * The result of this method is given to getDefaultTimeZone(String)
- * which tries to map the time zone id to a known TimeZone.  See
- * that method on how the returned String is mapped to a real
- * TimeZone object.
- */
-jstring
-java::util::TimeZone::getDefaultTimeZoneId ()
-{
-  struct tm tim;
-#ifndef HAVE_LOCALTIME_R
-  struct tm *lt_tim;
-#endif
-#ifdef HAVE_TM_ZONE
-  int month;
-#endif
-  time_t current_time;
-  long tzoffset;
-  const char *tz1, *tz2;
-  char *tzid;
-
-  time(&current_time);
-#ifdef HAVE_LOCALTIME_R
-  localtime_r(&current_time, &tim);
-#else
-  /* Fall back on non-thread safe localtime. */
-  lt_tim = localtime(&current_time);
-  memcpy(&tim, lt_tim, sizeof (struct tm));
-#endif
-  mktime(&tim);
-
-#ifdef HAVE_TM_ZONE
-  /* We will cycle through the months to make sure we hit dst. */
-  month = tim.tm_mon;
-  tz1 = tz2 = NULL;
-  while (tz1 == NULL || tz2 == NULL)
-    {
-      if (tim.tm_isdst > 0)
-        tz2 = tim.tm_zone;
-      else if (tz1 == NULL)
-        {
-          tz1 = tim.tm_zone;
-          month = tim.tm_mon;
-        }
-
-      if (tz1 == NULL || tz2 == NULL)
-        {
-          tim.tm_mon++;
-          tim.tm_mon %= 12;
-        }
-
-      if (tim.tm_mon == month && tz2 == NULL)
-        tz2 = "";
-      else
-        mktime(&tim);
-    }
-  /* We want to make sure the tm struct we use later on is not dst. */
-  tim.tm_mon = month;
-  mktime(&tim);
-#elif defined (HAVE_TZNAME)
-  /* If dst is never used, tzname[1] is the empty string. */
-  tzset();
-  tz1 = tzname[0];
-  tz2 = tzname[1];
-#else
-  /* Some targets have no concept of timezones. Assume GMT without dst. */
-  tz1 = "GMT";
-  tz2 = "";
-#endif
-
-#ifdef STRUCT_TM_HAS_GMTOFF
-  /* tm_gmtoff is the number of seconds that you must add to GMT to get
-     local time, we need the number of seconds to add to the local time
-     to get GMT. */
-  tzoffset = -1L * tim.tm_gmtoff;
-#elif HAVE_UNDERSCORE_TIMEZONE
-  tzoffset = _timezone;
-#elif HAVE_TIMEZONE
-  /* timezone is secs WEST of UTC. */
-  tzoffset = timezone; 
-#else
-  /* FIXME: there must be another global if neither tm_gmtoff nor timezone
-     is available, esp. if tzname is valid.
-     Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to
-     calculate between gmtime and localtime (and accounting for possible
-     daylight savings time) as an alternative. */
-  tzoffset = 0L;
-#endif
-
-  if ((tzoffset % 3600) == 0)
-    tzoffset = tzoffset / 3600;
-
-  tzid = (char*) _Jv_Malloc (strlen(tz1) + strlen(tz2) + 6);
-  sprintf(tzid, "%s%ld%s", tz1, tzoffset, tz2);
-  jstring retval = JvNewStringUTF (tzid);
-  _Jv_Free (tzid);
-
-  return retval;
-}
diff --git a/libjava/java/util/natVMTimeZone.cc b/libjava/java/util/natVMTimeZone.cc
new file mode 100644 (file)
index 0000000..a6d7016
--- /dev/null
@@ -0,0 +1,145 @@
+// natVMTimeZone.cc -- Native side of VMTimeZone class.
+
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+#include <config.h>
+#include <platform.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/util/VMTimeZone.h>
+#include <java/lang/Character.h>
+#include <java/lang/Integer.h>
+
+#include <stdio.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <string.h>
+
+/**
+ * This method returns a time zone id string which is in the form
+ * (standard zone name) or (standard zone name)(GMT offset) or
+ * (standard zone name)(GMT offset)(daylight time zone name).  The
+ * GMT offset can be in seconds, or where it is evenly divisible by
+ * 3600, then it can be in hours.  The offset must be the time to
+ * add to the local time to get GMT.  If a offset is given and the
+ * time zone observes daylight saving then the (daylight time zone
+ * name) must also be given (otherwise it is assumed the time zone
+ * does not observe any daylight savings).
+ * <p>
+ * The result of this method is given to getDefaultTimeZone(String)
+ * which tries to map the time zone id to a known TimeZone.  See
+ * that method on how the returned String is mapped to a real
+ * TimeZone object.
+ */
+jstring
+java::util::VMTimeZone::getSystemTimeZoneId()
+{
+  struct tm tim;
+#ifndef HAVE_LOCALTIME_R
+  struct tm *lt_tim;
+#endif
+#ifdef HAVE_TM_ZONE
+  int month;
+#endif
+  time_t current_time;
+  long tzoffset;
+  const char *tz1, *tz2;
+  char *tzid;
+
+  time(&current_time);
+#ifdef HAVE_LOCALTIME_R
+  localtime_r(&current_time, &tim);
+#else
+  /* Fall back on non-thread safe localtime. */
+  lt_tim = localtime(&current_time);
+  memcpy(&tim, lt_tim, sizeof (struct tm));
+#endif
+  mktime(&tim);
+
+#ifdef HAVE_TM_ZONE
+  /* We will cycle through the months to make sure we hit dst. */
+  month = tim.tm_mon;
+  tz1 = tz2 = NULL;
+  while (tz1 == NULL || tz2 == NULL)
+    {
+      if (tim.tm_isdst > 0)
+        tz2 = tim.tm_zone;
+      else if (tz1 == NULL)
+        {
+          tz1 = tim.tm_zone;
+          month = tim.tm_mon;
+        }
+
+      if (tz1 == NULL || tz2 == NULL)
+        {
+          tim.tm_mon++;
+          tim.tm_mon %= 12;
+        }
+
+      if (tim.tm_mon == month && tz2 == NULL)
+        tz2 = "";
+      else
+        mktime(&tim);
+    }
+  /* We want to make sure the tm struct we use later on is not dst. */
+  tim.tm_mon = month;
+  mktime(&tim);
+#elif defined (HAVE_TZNAME)
+  /* If dst is never used, tzname[1] is the empty string. */
+  tzset();
+  tz1 = tzname[0];
+  tz2 = tzname[1];
+#else
+  /* Some targets have no concept of timezones. Assume GMT without dst. */
+  tz1 = "GMT";
+  tz2 = "";
+#endif
+
+#ifdef STRUCT_TM_HAS_GMTOFF
+  /* tm_gmtoff is the number of seconds that you must add to GMT to get
+     local time, we need the number of seconds to add to the local time
+     to get GMT. */
+  tzoffset = -1L * tim.tm_gmtoff;
+#elif HAVE_UNDERSCORE_TIMEZONE
+  tzoffset = _timezone;
+#elif HAVE_TIMEZONE
+  /* timezone is secs WEST of UTC. */
+  tzoffset = timezone; 
+#else
+  /* FIXME: there must be another global if neither tm_gmtoff nor timezone
+     is available, esp. if tzname is valid.
+     Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to
+     calculate between gmtime and localtime (and accounting for possible
+     daylight savings time) as an alternative. */
+  tzoffset = 0L;
+#endif
+
+  if ((tzoffset % 3600) == 0)
+    tzoffset = tzoffset / 3600;
+
+  tzid = (char*) _Jv_Malloc (strlen(tz1) + strlen(tz2) + 6);
+  sprintf(tzid, "%s%ld%s", tz1, tzoffset, tz2);
+  jstring retval = JvNewStringUTF (tzid);
+  _Jv_Free (tzid);
+
+  return retval;
+}