Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (C) 2012 RoboVM AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package libcore.util;
import java.io.File;
import java.io.IOException;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.TreeSet;
import libcore.io.BufferIterator;
import libcore.io.HeapBufferIterator;
import libcore.io.IoUtils;
/**
* BugVM implementation of {@link ZoneInfoDB.TzData} which loads the zoneinfo
* from a standard Olson tzdata folder structure as used in Mac OS X, iOS and
* most Linux distributions.
*/
final class TzDataBugVM extends ZoneInfoDB.TzData {
private static final String ZONE_DIRECTORY_NAME = "/usr/share/zoneinfo/";
private static final String VERSION = readVersion();
/**
* Deprecated TimeZone aliases for JDK 1.1.x compatibility. We use the same mappings as used by GCJ.
*/
private static final Map deprecatedAliases;
/**
* Cached {@link ZoneInfo}s. The first time a ZoneInfo is loaded we store it in this array at the same
* index as the index of the timezone's id in ids. Subsequent calls for the same TimeZone will return a clone
* of the cached ZoneInfo.
*/
private static ZoneInfo[] zoneInfos;
/**
* The contents of the zone.tab file. Lazily loaded.
*/
private String zoneTab;
/**
* The 'ids' array contains time zone ids sorted alphabetically, for binary searching.
*/
private static String[] ids;
static {
deprecatedAliases = new HashMap();
deprecatedAliases.put("ACT", "Australia/Darwin");
deprecatedAliases.put("AET", "Australia/Sydney");
deprecatedAliases.put("AGT", "America/Argentina/Buenos_Aires");
deprecatedAliases.put("ART", "Africa/Cairo");
deprecatedAliases.put("AST", "America/Juneau");
deprecatedAliases.put("BET", "Etc/GMT-11");
deprecatedAliases.put("BST", "Asia/Colombo");
deprecatedAliases.put("CAT", "Africa/Gaborone");
deprecatedAliases.put("CNT", "America/St_Johns");
deprecatedAliases.put("CST", "CST6CDT");
deprecatedAliases.put("CTT", "Asia/Brunei");
deprecatedAliases.put("EAT", "Indian/Comoro");
deprecatedAliases.put("ECT", "CET");
deprecatedAliases.put("EST", "EST5EDT");
deprecatedAliases.put("EST5", "EST5EDT");
deprecatedAliases.put("IET", "EST5EDT");
deprecatedAliases.put("IST", "Asia/Calcutta");
deprecatedAliases.put("JST", "Asia/Seoul");
deprecatedAliases.put("MIT", "Pacific/Niue");
deprecatedAliases.put("MST", "MST7MDT");
deprecatedAliases.put("MST7", "MST7MDT");
deprecatedAliases.put("NET", "Indian/Mauritius");
deprecatedAliases.put("NST", "Pacific/Auckland");
deprecatedAliases.put("PLT", "Indian/Kerguelen");
deprecatedAliases.put("PNT", "MST7MDT");
deprecatedAliases.put("PRT", "America/Anguilla");
deprecatedAliases.put("PST", "PST8PDT");
deprecatedAliases.put("SST", "Pacific/Ponape");
deprecatedAliases.put("VST", "Asia/Bangkok");
readIndex();
}
/**
* Reads the file indicating the database version in use.
*/
private static String readVersion() {
// Mac OS X / iOS have a +VERSION file in /usr/share/zoneinfo containing the version number
try {
byte[] bytes = IoUtils.readFileAsByteArray(ZONE_DIRECTORY_NAME + "+VERSION");
return new String(bytes, 0, bytes.length, StandardCharsets.ISO_8859_1).trim();
} catch (IOException ex) {
// Linux (at least Ubuntu) doesn't have a +VERSION file. Just return unknown.
return "unknown";
}
}
/**
* Traditionally, Unix systems have one file per time zone. We have one big data file, which
* is just a concatenation of regular time zone files. To allow random access into this big
* data file, we also have an index. We read the index at startup, and keep it in memory so
* we can binary search by id when we need time zone data.
*
* The format of this file is, I believe, Android's own, and undocumented.
*
* All this code assumes strings are US-ASCII.
*/
private static void readIndex() {
try {
readIndexMulti();
} catch (Exception ex) {
throw new AssertionError(ex);
}
zoneInfos = new ZoneInfo[ids.length];
}
/**
* Populates the ids array when using a multi file timezone database. Reads the contents of
* {@link #ZONE_DIRECTORY_NAME}. We assume that all files beginning with an upper case letter at depth 0 to 2 are
* proper TZ files. Fragile but known to work on Ubuntu 12.04, Mac OS X 10.7 and iOS 6.0.
* This was added in BugVM.
*/
private static void readIndexMulti() throws IOException {
TreeSet set = new TreeSet();
for (File f1 : new File(ZONE_DIRECTORY_NAME).listFiles()) {
String name1 = f1.getName();
if ("Factory".equals(name1)) {
// Skip
continue;
}
if (name1.charAt(0) < 'A' || name1.charAt(0) > 'Z') {
// Must start with upper case character. Skip.
continue;
}
if (f1.isDirectory()) {
for (File f2 : f1.listFiles()) {
String name2 = f2.getName();
if (name2.charAt(0) < 'A' || name2.charAt(0) > 'Z') {
// Must start with upper case character. Skip.
continue;
}
if (f2.isDirectory()) {
for (File f3 : f2.listFiles()) {
String name3 = f3.getName();
if (name3.charAt(0) < 'A' || name3.charAt(0) > 'Z') {
// Must start with upper case character. Skip.
continue;
}
if (!f3.isDirectory()) {
set.add(name1 + "/" + name2 + "/" + name3);
}
}
} else {
set.add(name1 + "/" + name2);
}
}
} else {
set.add(name1);
}
}
for (Entry alias : deprecatedAliases.entrySet()) {
if (set.contains(alias.getValue())) {
set.add(alias.getKey());
}
}
ids = set.toArray(new String[set.size()]);
}
public TimeZone makeTimeZone(String id) throws IOException {
return makeTimeZone(id, true);
}
private TimeZone makeTimeZone(String id, boolean clone) throws IOException {
// Check the aliases first
String realId = deprecatedAliases.get(id);
if (realId != null) {
return makeTimeZone(realId, clone);
}
// Work out where in the big data file this time zone is.
int index = Arrays.binarySearch(ids, id);
if (index < 0) {
return null;
}
ZoneInfo zoneInfo = zoneInfos[index];
if (zoneInfo != null) {
return clone ? (TimeZone) zoneInfo.clone() : zoneInfo;
}
byte[] bytes = IoUtils.readFileAsByteArray(ZONE_DIRECTORY_NAME + id);
BufferIterator it = HeapBufferIterator.iterator(bytes, 0, bytes.length, ByteOrder.BIG_ENDIAN);
zoneInfo = (ZoneInfo) ZoneInfo.makeTimeZone(id, it);
zoneInfos[index] = zoneInfo;
return clone ? (TimeZone) zoneInfo.clone() : zoneInfo;
}
public String[] getAvailableIDs() {
return ids.clone();
}
public String[] getAvailableIDs(int rawOffset) {
List matches = new ArrayList();
// Unfortunately we need load each ZoneInfo to determine the offset
for (String id : ids) {
try {
TimeZone timeZone = makeTimeZone(id, false);
if (timeZone.getRawOffset() == rawOffset) {
matches.add(id);
}
} catch (IOException e) {
}
}
return matches.toArray(new String[matches.size()]);
}
public String getZoneTab() {
if (zoneTab == null) {
try {
zoneTab = IoUtils.readFileAsString(ZONE_DIRECTORY_NAME + "zone.tab");
} catch (IOException e) {
throw new Error(e);
}
}
return zoneTab;
}
@Override
public String getDefaultID() {
// In BugVM we check the files /etc/timezone, /etc/localtime and /private/var/db/timezone/localtime.
// The first file is a text file containing the id of the current time zone, e.g. 'Europe/Stockholm'
// The two other files should be symlinks into the /usr/share/zoneinfo dir pointing out the current
// time zone.
String zoneName = null;
try {
// Ubuntu places the time zone in /etc/timezone
zoneName = IoUtils.readFileAsString("/etc/timezone").trim();
} catch (IOException e) {
}
if (zoneName == null || zoneName.isEmpty()) {
// Mac OS X symlinks /etc/localtime to the current time zone file in /usr/share/zoneinfo
File link = new File("/etc/localtime");
if (!link.exists()) {
// iOS uses the link /private/var/db/timezone/localtime instead
link = new File("/private/var/db/timezone/localtime");
}
try {
String path = link.getCanonicalPath(); // Resolve the link
for (String id : ids) {
if (path.endsWith(id)) {
zoneName = id;
}
}
} catch (IOException e) {
}
}
return zoneName;
}
public String getVersion() {
return VERSION;
}
}