1071 lines · 34.9 KB · Java
RawDownload
/* * Copyright (c) 2000, 2010, 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 * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.util.calendar; import  java.io.File;import  java.io.FileInputStream;import  java.io.FileNotFoundException;import  java.io.IOException;import  java.lang.ref.SoftReference;import  java.nio.file.FileSystems;import  java.security.AccessController;import  java.security.PrivilegedAction;import  java.security.PrivilegedActionException;import  java.security.PrivilegedExceptionAction;import  java.util.ArrayList;import  java.util.HashMap;import  java.util.List;import  java.util.Map; /** * <code>ZoneInfoFile</code> reads Zone information files in the * &lt;java.home&gt;/lib/zi directory and provides time zone * information in the form of a {@link ZoneInfo} object. Also, it * reads the ZoneInfoMappings file to obtain time zone IDs information * that is used by the {@link ZoneInfo} class. The directory layout * and data file formats are as follows. * * <p><strong>Directory layout</strong><p> * * All zone data files and ZoneInfoMappings are put under the * &lt;java.home&gt;/lib/zi directory. A path name for a given time * zone ID is a concatenation of &lt;java.home&gt;/lib/zi/ and the * time zone ID. (The file separator is replaced with the platform * dependent value. e.g., '\' for Win32.) An example layout will look * like as follows. * <blockquote> * <pre> * &lt;java.home&gt;/lib/zi/Africa/Addis_Ababa *                   /Africa/Dakar *                   /America/Los_Angeles *                   /Asia/Singapore *                   /EET *                   /Europe/Oslo *                   /GMT *                   /Pacific/Galapagos *                       ... *                   /ZoneInfoMappings * </pre> * </blockquote> * * A zone data file has specific information of each zone. * <code>ZoneInfoMappings</code> has global information of zone IDs so * that the information can be obtained without instantiating all time * zones. * * <p><strong>File format</strong><p> * * Two binary-file formats based on a simple Tag-Length-Value format are used * to describe TimeZone information. The generic format of a data file is: * <blockquote> * <pre> *    DataFile { *      u1              magic[7]; *      u1              version; *      data_item       data[]; *    } * </pre> * </blockquote> * where <code>magic</code> is a magic number identifying a file * format, <code>version</code> is the format version number, and * <code>data</code> is one or more <code>data_item</code>s. The * <code>data_item</code> structure is: * <blockquote> * <pre> *    data_item { *      u1              tag; *      u2              length; *      u1              value[length]; *    } * </pre> * </blockquote> * where <code>tag</code> indicates the data type of the item, * <code>length</code> is a byte count of the following * <code>value</code> that is the content of item data. * <p> * All data is stored in the big-endian order. There is no boundary * alignment between date items. * * <p><strong>1. ZoneInfo data file</strong><p> * * Each ZoneInfo data file consists of the following members. * <br> * <blockquote> * <pre> *    ZoneInfoDataFile { *      u1              magic[7]; *      u1              version; *      SET OF<sup>1</sup> { *        transition            transitions<sup>2</sup>; *        offset_table          offsets<sup>2</sup>; *        simpletimezone        stzparams<sup>2</sup>; *        raw_offset            rawoffset; *        dstsaving             dst; *        checksum              crc32; *        gmtoffsetwillchange   gmtflag<sup>2</sup>; *      } *   } *   1: an unordered collection of zero or one occurrences of each item *   2: optional item * </pre> * </blockquote> * <code>magic</code> is a byte-string constant identifying the * ZoneInfo data file.  This field must be <code>"javazi&#92;0"</code> * defined as {@link #JAVAZI_LABEL}. * <p> * <code>version</code> is the version number of the file format. This * will be used for compatibility check. This field must be * <code>0x01</code> in this version. * <p> * <code>transition</code>, <code>offset_table</code> and * <code>simpletimezone</code> have information of time transition * from the past to the future.  Therefore, these structures don't * exist if the zone didn't change zone names and haven't applied DST in * the past, and haven't planned to apply it.  (e.g. Asia/Tokyo zone) * <p> * <code>raw_offset</code>, <code>dstsaving</code> and <code>checksum</code> * exist in every zoneinfo file. They are used by TimeZone.class indirectly. * * <p><strong>1.1 <code>transition</code> structure</strong><p><a name="transition"></a> * <blockquote> * <pre> *    transition { *      u1      tag;              // 0x04 : constant *      u2      length;           // byte length of whole values *      s8      value[length/8];  // transitions in `long' *    } * </pre> * </blockquote> * See {@link ZoneInfo#transitions ZoneInfo.transitions} about the value. * * <p><strong>1.2 <code>offset_table</code> structure</strong><p> * <blockquote> * <pre> *    offset_table { *      u1      tag;              // 0x05 : constant *      u2      length;           // byte length of whole values *      s4      value[length/4];  // offset values in `int' *    } * </pre> * </blockquote> * * <p><strong>1.3 <code>simpletimezone</code> structure</strong><p> * See {@link ZoneInfo#simpleTimeZoneParams ZoneInfo.simpleTimeZoneParams} * about the value. * <blockquote> * <pre> *    simpletimezone { *      u1      tag;              // 0x06 : constant *      u2      length;           // byte length of whole values *      s4      value[length/4];  // SimpleTimeZone parameters *    } * </pre> * </blockquote> * See {@link ZoneInfo#offsets ZoneInfo.offsets} about the value. * * <p><strong>1.4 <code>raw_offset</code> structure</strong><p> * <blockquote> * <pre> *    raw_offset { *      u1      tag;              // 0x01 : constant *      u2      length;           // must be 4. *      s4      value;            // raw GMT offset [millisecond] *    } * </pre> * </blockquote> * See {@link ZoneInfo#rawOffset ZoneInfo.rawOffset} about the value. * * <p><strong>1.5 <code>dstsaving</code> structure</strong><p> * Value has dstSaving in seconds. * <blockquote> * <pre> *    dstsaving { *      u1      tag;              // 0x02 : constant *      u2      length;           // must be 2. *      s2      value;            // DST save value [second] *    } * </pre> * </blockquote> * See {@link ZoneInfo#dstSavings ZoneInfo.dstSavings} about value. * * <p><strong>1.6 <code>checksum</code> structure</strong><p> * <blockquote> * <pre> *    checksum { *      u1      tag;              // 0x03 : constant *      u2      length;           // must be 4. *      s4      value;            // CRC32 value of transitions *    } * </pre> * </blockquote> * See {@link ZoneInfo#checksum ZoneInfo.checksum}. * * <p><strong>1.7 <code>gmtoffsetwillchange</code> structure</strong><p> * This record has a flag value for {@link ZoneInfo#rawOffsetWillChange}. * If this record is not present in a zoneinfo file, 0 is assumed for * the value. * <blockquote> * <pre> *    gmtoffsetwillchange { *      u1      tag;             // 0x07 : constant *      u2      length;          // must be 1. *      u1      value;           // 1: if the GMT raw offset will change *                               // in the future, 0, otherwise. *     } * </pre> * </blockquote> * * * <p><strong>2. ZoneInfoMappings file</strong><p> * * The ZoneInfoMappings file consists of the following members. * <br> * <blockquote> * <pre> *    ZoneInfoMappings { *      u1      magic[7]; *      u1      version; *      SET OF { *        versionName                   version; *        zone_id_table                 zoneIDs; *        raw_offset_table              rawoffsets; *        raw_offset_index_table        rawoffsetindices; *        alias_table                   aliases; *        excluded_list                 excludedList; *      } *   } * </pre> * </blockquote> * * <code>magic</code> is a byte-string constant which has the file type. * This field must be <code>"javazm&#92;0"</code> defined as {@link #JAVAZM_LABEL}. * <p> * <code>version</code> is the version number of this file * format. This will be used for compatibility check. This field must * be <code>0x01</code> in this version. * <p> * <code>versionName</code> shows which version of Olson's data has been used * to generate this ZoneInfoMappings. (e.g. <code>tzdata2000g</code>) <br> * This field is for trouble-shooting and isn't usually used in runtime. * <p> * <code>zone_id_table</code>, <code>raw_offset_index_table</code> and * <code>alias_table</code> are general information of supported * zones. * * <p><strong>2.1 <code>zone_id_table</code> structure</strong><p> * The list of zone IDs included in the zi database. The list does * <em>not</em> include zone IDs, if any, listed in excludedList. * <br> * <blockquote> * <pre> *    zone_id_table { *      u1      tag;              // 0x40 : constant *      u2      length;           // byte length of whole values *      u2      zone_id_count; *      zone_id value[zone_id_count]; *    } * *    zone_id { *      u1      byte_length;      // byte length of id *      u1      id[byte_length];  // zone name string *    } * </pre> * </blockquote> * * <p><strong>2.2 <code>raw_offset_table</code> structure</strong><p> * <br> * <blockquote> * <pre> *    raw_offset_table { *      u1      tag;              // 0x41 : constant *      u2      length;           // byte length of whole values *      s4      value[length/4];  // raw GMT offset in milliseconds *   } * </pre> * </blockquote> * * <p><strong>2.3 <code>raw_offset_index_table</code> structure</strong><p> * <br> * <blockquote> * <pre> *    raw_offset_index_table { *      u1      tag;              // 0x42 : constant *      u2      length;           // byte length of whole values *      u1      value[length]; *    } * </pre> * </blockquote> * * <p><strong>2.4 <code>alias_table</code> structure</strong><p> * <br> * <blockquote> * <pre> *   alias_table { *      u1      tag;              // 0x43 : constant *      u2      length;           // byte length of whole values *      u2      nentries;         // number of id-pairs *      id_pair value[nentries]; *   } * *   id_pair { *      zone_id aliasname; *      zone_id ID; *   } * </pre> * </blockquote> * * <p><strong>2.5 <code>versionName</code> structure</strong><p> * <br> * <blockquote> * <pre> *   versionName { *      u1      tag;              // 0x44 : constant *      u2      length;           // byte length of whole values *      u1      value[length]; *   } * </pre> * </blockquote> * * <p><strong>2.6 <code>excludeList</code> structure</strong><p> * The list of zone IDs whose zones will change their GMT offsets * (a.k.a. raw offsets) some time in the future. Those IDs must be * added to the list of zone IDs for getAvailableIDs(). Also they must * be examined for getAvailableIDs(int) to determine the * <em>current</em> GMT offsets. * <br> * <blockquote> * <pre> *   excluded_list { *      u1      tag;              // 0x45 : constant *      u2      length;           // byte length of whole values *      u2      nentries;         // number of zone_ids *      zone_id value[nentries];  // excluded zone IDs *   } * </pre> * </blockquote> * * @since 1.4 */ public class ZoneInfoFile {     /**     * The magic number for the ZoneInfo data file format.     */    public static final byte[]  JAVAZI_LABEL = {        (byte)'j', (byte)'a', (byte)'v', (byte)'a', (byte)'z', (byte)'i', (byte)'\0'    };    private static final int    JAVAZI_LABEL_LENGTH = JAVAZI_LABEL.length;     /**     * The ZoneInfo data file format version number. Must increase     * one when any incompatible change has been made.     */    public static final byte    JAVAZI_VERSION = 0x01;     /**     * Raw offset data item tag.     */    public static final byte    TAG_RawOffset = 1;     /**     * Known last Daylight Saving Time save value data item tag.     */    public static final byte    TAG_LastDSTSaving = 2;     /**     * Checksum data item tag.     */    public static final byte    TAG_CRC32 = 3;     /**     * Transition data item tag.     */    public static final byte    TAG_Transition = 4;     /**     * Offset table data item tag.     */    public static final byte    TAG_Offset = 5;     /**     * SimpleTimeZone parameters data item tag.     */    public static final byte    TAG_SimpleTimeZone = 6;     /**     * Raw GMT offset will change in the future.     */    public static final byte    TAG_GMTOffsetWillChange = 7;      /**     * The ZoneInfoMappings file name.     */    public static final String  JAVAZM_FILE_NAME = "ZoneInfoMappings";     /**     * The magic number for the ZoneInfoMappings file format.     */    public static final byte[]  JAVAZM_LABEL = {        (byte)'j', (byte)'a', (byte)'v', (byte)'a', (byte)'z', (byte)'m', (byte)'\0'    };    private static final int    JAVAZM_LABEL_LENGTH = JAVAZM_LABEL.length;     /**     * The ZoneInfoMappings file format version number. Must increase     * one when any incompatible change has been made.     */    public static final byte    JAVAZM_VERSION = 0x01;     /**     * Time zone IDs data item tag.     */    public static final byte    TAG_ZoneIDs = 64;     /**     * Raw GMT offsets table data item tag.     */    public static final byte    TAG_RawOffsets = 65;     /**     * Indices to the raw GMT offset table data item tag.     */    public static final byte    TAG_RawOffsetIndices = 66;     /**     * Time zone aliases table data item tag.     */    public static final byte    TAG_ZoneAliases = 67;     /**     * Olson's public zone information version tag.     */    public static final byte    TAG_TZDataVersion = 68;     /**     * Excluded zones item tag. (Added in Mustang)     */    public static final byte    TAG_ExcludedZones = 69;     private static Map<String, ZoneInfo> zoneInfoObjects = null;     private static final String ziDir = AccessController.doPrivileged(        new PrivilegedAction<String>() {            public String run() {                String zi = System.getProperty("java.home") +                    File.separator + "lib" + File.separator + "zi";                try {                    zi = FileSystems.getDefault().getPath(zi).toRealPath().toString();                } catch(Exception e) {                }                return zi;            }        });     /**     * Converts the given time zone ID to a platform dependent path     * name. For example, "America/Los_Angeles" is converted to     * "America\Los_Angeles" on Win32.     * @return a modified ID replacing '/' with {@link     * java.io.File#separatorChar File.separatorChar} if needed.     */    public static String getFileName(String ID) {        if (File.separatorChar == '/') {            return ID;        }        return ID.replace('/', File.separatorChar);

Lines 1–500 of 1071.