/*
* Copyright (c) 2000, 2012, 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;
/**
* ZoneInfoFile reads Zone information files in the
* <java.home>/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.
*
*
Directory layout
* * All zone data files and ZoneInfoMappings are put under the * <java.home>/lib/zi directory. A path name for a given time * zone ID is a concatenation of <java.home>/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. *
** * A zone data file has specific information of each zone. ** <java.home>/lib/zi/Africa/Addis_Ababa * /Africa/Dakar * /America/Los_Angeles * /Asia/Singapore * /EET * /Europe/Oslo * /GMT * /Pacific/Galapagos * ... * /ZoneInfoMappings **
ZoneInfoMappings has global information of zone IDs so
* that the information can be obtained without instantiating all time
* zones.
*
* File format
* * 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: *
*
* DataFile {
* u1 magic[7];
* u1 version;
* data_item data[];
* }
*
*
* where magic is a magic number identifying a file
* format, version is the format version number, and
* data is one or more data_items. The
* data_item structure is:
*
*
* data_item {
* u1 tag;
* u2 length;
* u1 value[length];
* }
*
*
* where tag indicates the data type of the item,
* length is a byte count of the following
* value that is the content of item data.
* * All data is stored in the big-endian order. There is no boundary * alignment between date items. * *
1. ZoneInfo data file
*
* Each ZoneInfo data file consists of the following members.
*
*
*
* ZoneInfoDataFile {
* u1 magic[7];
* u1 version;
* SET OF1 {
* transition transitions2;
* offset_table offsets2;
* simpletimezone stzparams2;
* raw_offset rawoffset;
* dstsaving dst;
* checksum crc32;
* gmtoffsetwillchange gmtflag2;
* }
* }
* 1: an unordered collection of zero or one occurrences of each item
* 2: optional item
*
*
* magic is a byte-string constant identifying the
* ZoneInfo data file. This field must be "javazi\0"
* defined as {@link #JAVAZI_LABEL}.
*
* version is the version number of the file format. This
* will be used for compatibility check. This field must be
* 0x01 in this version.
*
* transition, offset_table and
* simpletimezone 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)
*
* raw_offset, dstsaving and checksum
* exist in every zoneinfo file. They are used by TimeZone.class indirectly.
*
*
1.1 transition structure
*
* transition {
* u1 tag; // 0x04 : constant
* u2 length; // byte length of whole values
* s8 value[length/8]; // transitions in `long'
* }
*
*
* See {@link ZoneInfo#transitions ZoneInfo.transitions} about the value.
*
* 1.2 offset_table structure
*
*
* offset_table {
* u1 tag; // 0x05 : constant
* u2 length; // byte length of whole values
* s4 value[length/4]; // offset values in `int'
* }
*
*
*
* 1.3 simpletimezone structure
* See {@link ZoneInfo#simpleTimeZoneParams ZoneInfo.simpleTimeZoneParams} * about the value. *
*
* simpletimezone {
* u1 tag; // 0x06 : constant
* u2 length; // byte length of whole values
* s4 value[length/4]; // SimpleTimeZone parameters
* }
*
*
* See {@link ZoneInfo#offsets ZoneInfo.offsets} about the value.
*
* 1.4 raw_offset structure
*
*
* raw_offset {
* u1 tag; // 0x01 : constant
* u2 length; // must be 4.
* s4 value; // raw GMT offset [millisecond]
* }
*
*
* See {@link ZoneInfo#rawOffset ZoneInfo.rawOffset} about the value.
*
* 1.5 dstsaving structure
* Value has dstSaving in seconds. *
*
* dstsaving {
* u1 tag; // 0x02 : constant
* u2 length; // must be 2.
* s2 value; // DST save value [second]
* }
*
*
* See {@link ZoneInfo#dstSavings ZoneInfo.dstSavings} about value.
*
* 1.6 checksum structure
*
*
* checksum {
* u1 tag; // 0x03 : constant
* u2 length; // must be 4.
* s4 value; // CRC32 value of transitions
* }
*
*
* See {@link ZoneInfo#checksum ZoneInfo.checksum}.
*
* 1.7 gmtoffsetwillchange structure
* 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. *
*
* 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.
* }
*
*
*
*
* 2. ZoneInfoMappings file
*
* The ZoneInfoMappings file consists of the following members.
*
*
*
* 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;
* }
* }
*
*
*
* magic is a byte-string constant which has the file type.
* This field must be "javazm\0" defined as {@link #JAVAZM_LABEL}.
*
* version is the version number of this file
* format. This will be used for compatibility check. This field must
* be 0x01 in this version.
*
* versionName shows which version of Olson's data has been used
* to generate this ZoneInfoMappings. (e.g. tzdata2000g)
* This field is for trouble-shooting and isn't usually used in runtime.
*
* zone_id_table, raw_offset_index_table and
* alias_table are general information of supported
* zones.
*
*
2.1 zone_id_table structure
* The list of zone IDs included in the zi database. The list does
* not include zone IDs, if any, listed in excludedList.
*
*
*
* 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
* }
*
*
*
* 2.2 raw_offset_table structure
*
*
*
* raw_offset_table {
* u1 tag; // 0x41 : constant
* u2 length; // byte length of whole values
* s4 value[length/4]; // raw GMT offset in milliseconds
* }
*
*
*
* 2.3 raw_offset_index_table structure
*
*
*
* raw_offset_index_table {
* u1 tag; // 0x42 : constant
* u2 length; // byte length of whole values
* u1 value[length];
* }
*
*
*
* 2.4 alias_table structure
*
*
*
* 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;
* }
*
*
*
* 2.5 versionName structure
*
*
*
* versionName {
* u1 tag; // 0x44 : constant
* u2 length; // byte length of whole values
* u1 value[length];
* }
*
*
*
* 2.6 excludeList structure
* 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
* current GMT offsets.
*
*
*
* 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
* }
*
*
*
* @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