From ffe2e220bdb8fee858045b645601923656864cc5 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 25 Sep 2004 22:21:51 +0000 Subject: [PATCH] [multiple changes] 2004-09-25 Mark Wielaard * 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 * java/util/TimeZone.java (getDefaultTimeZone): Fixed test to distinguish between hours and minutes in specified timezone. From-SVN: r88112 --- libjava/ChangeLog | 24 ++ libjava/Makefile.am | 3 +- libjava/Makefile.in | 26 +- libjava/gcj/javaprims.h | 2 + libjava/java/util/TimeZone.java | 292 +-------------- libjava/java/util/VMTimeZone.java | 345 ++++++++++++++++++ .../util/{natTimeZone.cc => natVMTimeZone.cc} | 6 +- 7 files changed, 404 insertions(+), 294 deletions(-) create mode 100644 libjava/java/util/VMTimeZone.java rename libjava/java/util/{natTimeZone.cc => natVMTimeZone.cc} (96%) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index dd323d30e82..4e1c6879907 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,27 @@ +2004-09-25 Mark Wielaard + + * 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 + + * java/util/TimeZone.java + (getDefaultTimeZone): Fixed test to distinguish between hours and + minutes in specified timezone. + 2004-09-25 Jeroen Frijters * java/lang/reflect/Proxy.java (getPackage, ClassFactory): Fixed diff --git a/libjava/Makefile.am b/libjava/Makefile.am index b126ab2c256..543b48879f5 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -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 diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 083bf097ce2..bd831fea3e5 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -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@ diff --git a/libjava/gcj/javaprims.h b/libjava/gcj/javaprims.h index 8b2b090b95c..3120184650f 100644 --- a/libjava/gcj/javaprims.h +++ b/libjava/gcj/javaprims.h @@ -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; diff --git a/libjava/java/util/TimeZone.java b/libjava/java/util/TimeZone.java index cc3c7a3d283..1e06e535611 100644 --- a/libjava/java/util/TimeZone.java +++ b/libjava/java/util/TimeZone.java @@ -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 getDefaultTimeZone(String) with - * the result of - * System.getProperty("user.timezone"), - * System.getenv("TZ"), - * readTimeZoneFile("/etc/timezone"), - * readtzFile("/etc/localtime") and - * getDefaultTimeZoneId() - * till a supported TimeZone is found. - * If every method fails GMT is returned. + * the result of System.getProperty("user.timezone"). + * If that fails it calls VMTimeZone.getDefaultTimeZoneId(). + * 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). - *

- * 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. - *

- * 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 getDefaultTimeZone(String). - * If the file doesn't exist, an IOException occurs or it isn't a tzfile - * that can be parsed null is returned. - *

- * The tzfile structure (as also used by glibc) is described in the Olson - * tz database archive as can be found at - * ftp://elsie.nci.nih.gov/pub/. - *

- * 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 index 00000000000..77c055b2a64 --- /dev/null +++ b/libjava/java/util/VMTimeZone.java @@ -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). + *

+ * 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. + *

+ * The reference implementation which is made for GNU/Posix like + * systems calls System.getenv("TZ"), + * readTimeZoneFile("/etc/timezone"), + * readtzFile("/etc/localtime") and finally + * getSystemTimeZoneId() till a supported TimeZone is + * found through TimeZone.getDefaultTimeZone(String). + * If every method fails null is returned (which means + * the TimeZone code will fall back on GMT as default time zone). + *

+ * Note that this method is called inside a + * AccessController.doPrivileged() 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. + *

+ * 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 getDefaultTimeZone(String). + * If the file doesn't exist, an IOException occurs or it isn't a tzfile + * that can be parsed null is returned. + *

+ * The tzfile structure (as also used by glibc) is described in the Olson + * tz database archive as can be found at + * ftp://elsie.nci.nih.gov/pub/. + *

+ * 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/natVMTimeZone.cc similarity index 96% rename from libjava/java/util/natTimeZone.cc rename to libjava/java/util/natVMTimeZone.cc index c23d9e6555e..a6d701642f6 100644 --- a/libjava/java/util/natTimeZone.cc +++ b/libjava/java/util/natVMTimeZone.cc @@ -1,4 +1,4 @@ -// natTimeZone.cc -- Native side of TimeZone class. +// natVMTimeZone.cc -- Native side of VMTimeZone class. /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation @@ -15,7 +15,7 @@ details. */ #include #include -#include +#include #include #include @@ -51,7 +51,7 @@ details. */ * TimeZone object. */ jstring -java::util::TimeZone::getDefaultTimeZoneId () +java::util::VMTimeZone::getSystemTimeZoneId() { struct tm tim; #ifndef HAVE_LOCALTIME_R -- 2.30.2