Merge "Remove unused files from sun.nio.ch package"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index cb43851..ff0ae37 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -52,9 +52,10 @@
core_resource_dirs := \
luni/src/main/java \
ojluni/src/main/resources/
-test_resource_dirs := $(call all-core-resource-dirs,test)
+test_resource_dirs := $(filter-out ojluni/%,$(call all-core-resource-dirs,test))
test_src_files := $(call all-test-java-files-under,dalvik dalvik/test-rules dom harmony-tests json luni xml)
ojtest_src_files := $(call all-test-java-files-under,ojluni)
+ojtest_resource_dirs := $(filter ojluni/%,$(call all-core-resource-dirs,test))
ifeq ($(EMMA_INSTRUMENT),true)
ifneq ($(EMMA_INSTRUMENT_STATIC),true)
@@ -215,7 +216,8 @@
nist-pkix-tests \
slf4j-jdk14 \
sqlite-jdbc \
- tzdata-testing
+ tzdata-testing \
+ junit-params
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_ERROR_PRONE_FLAGS := -Xep:TryFailThrowable:ERROR
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -255,6 +257,7 @@
# Make the core-ojtests library.
ifeq ($(LIBCORE_SKIP_TESTS),)
include $(CLEAR_VARS)
+ LOCAL_JAVA_RESOURCE_DIRS := $(ojtest_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp bouncycastle
LOCAL_STATIC_JAVA_LIBRARIES := testng
@@ -272,10 +275,9 @@
ifeq ($(LIBCORE_SKIP_TESTS),)
include $(CLEAR_VARS)
# Filter out SerializedLambdaTest because it depends on stub classes and won't actually run.
- # Temporarily filter out java.time tests until they stabilize (b/28832222)
- LOCAL_SRC_FILES := $(filter-out ojluni/src/test/java/time/% %/DeserializeMethodTest.java %/SerializedLambdaTest.java ojluni/src/test/java/util/stream/boot%,$(ojtest_src_files)) # Do not include anything from the boot* directories. Those directories need a custom bootclasspath to run.
+ LOCAL_SRC_FILES := $(filter-out %/DeserializeMethodTest.java %/SerializedLambdaTest.java ojluni/src/test/java/util/stream/boot%,$(ojtest_src_files)) # Do not include anything from the boot* directories. Those directories need a custom bootclasspath to run.
# Include source code as part of JAR
- LOCAL_JAVA_RESOURCE_DIRS := ojluni/src/test/dist
+ LOCAL_JAVA_RESOURCE_DIRS := ojluni/src/test/dist $(ojtest_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := \
bouncycastle \
@@ -383,7 +385,8 @@
nist-pkix-tests-host \
slf4j-jdk14-hostdex \
sqlite-jdbc-host \
- tzdata-testing-hostdex
+ tzdata-testing-hostdex \
+ junit-params-hostdex
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java b/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java
index 83777b0..b479d6f 100644
--- a/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java
+++ b/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java
@@ -263,7 +263,7 @@
* Returns the size (in bytes) occupied by a given primitive type on an
* {@code EmulatedStackFrame}.
*/
- private static int getSize(Class<?> type) {
+ public static int getSize(Class<?> type) {
if (!type.isPrimitive()) {
throw new IllegalArgumentException("type.isPrimitive() == false: " + type);
}
@@ -377,6 +377,29 @@
referencesOffset = frame.references.length - 1;
}
}
+
+ public static void copyNext(StackFrameReader reader, StackFrameWriter writer,
+ Class<?> type) {
+ if (!type.isPrimitive()) {
+ writer.putNextReference(reader.nextReference(type), type);
+ } else if (type == boolean.class) {
+ writer.putNextBoolean(reader.nextBoolean());
+ } else if (type == byte.class) {
+ writer.putNextByte(reader.nextByte());
+ } else if (type == char.class) {
+ writer.putNextChar(reader.nextChar());
+ } else if (type == short.class) {
+ writer.putNextShort(reader.nextShort());
+ } else if (type == int.class) {
+ writer.putNextInt(reader.nextInt());
+ } else if (type == long.class) {
+ writer.putNextLong(reader.nextLong());
+ } else if (type == float.class) {
+ writer.putNextFloat(reader.nextFloat());
+ } else if (type == double.class) {
+ writer.putNextDouble(reader.nextDouble());
+ }
+ }
}
/**
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 76c16df..a5764f5 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1541,14 +1541,5 @@
names: [
"libcore.java.text.OldBidiTest#testUnicode9EmojisAreLtrNeutral"
]
-},
-{
- description: "Test failures due to incomplete java.time implementation.",
- bug: 28832222,
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.util.CalendarTest#test_getDisplayNameIILjava_util_Locale",
- "org.apache.harmony.tests.java.util.CalendarTest#test_getDisplayNamesIILjava_util_Locale"
- ]
}
]
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java
index e5742d7..4e41c2a 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/InetAddressTest.java
@@ -343,8 +343,9 @@
} catch (IllegalArgumentException e) {
// correct
}
- // tests nowhere
- ia = Inet4Address.getByName("1.1.1.1");
+ // tests nowhere using an address from the 'IPv4 Address Blocks Reserved for Documentation'
+ // as specified in https://tools.ietf.org/html/rfc5737
+ ia = Inet4Address.getByName("192.0.2.1");
assertFalse(ia.isReachable(1000));
assertFalse(ia.isReachable(null, 0, 1000));
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CalendarTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CalendarTest.java
index 06a37c8..6284f0f 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CalendarTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CalendarTest.java
@@ -968,7 +968,8 @@
.getAmPmStrings() : symbols.getEras();
assertDisplayNameMap(values, shortResult, 0);
assertDisplayNameMap(values, longResult, 0);
- assertDisplayNameMap(values, allResult, 0);
+ assertTrue(allResult.size() >= shortResult.size());
+ assertTrue(allResult.size() >= longResult.size());
break;
case Calendar.MONTH:
values = symbols.getShortMonths();
@@ -977,8 +978,6 @@
assertDisplayNameMap(values, longResult, 0);
assertTrue(allResult.size() >= shortResult.size());
assertTrue(allResult.size() >= longResult.size());
- assertTrue(allResult.size() <= shortResult.size()
- + longResult.size());
break;
case Calendar.DAY_OF_WEEK:
values = symbols.getShortWeekdays();
@@ -987,8 +986,6 @@
assertDisplayNameMap(values, longResult, 1);
assertTrue(allResult.size() >= shortResult.size());
assertTrue(allResult.size() >= longResult.size());
- assertTrue(allResult.size() <= shortResult.size()
- + longResult.size());
break;
default:
assertNull(shortResult);
diff --git a/luni/src/test/java/libcore/java/lang/SystemTest.java b/luni/src/test/java/libcore/java/lang/SystemTest.java
index 2dc9d49..2de659d 100644
--- a/luni/src/test/java/libcore/java/lang/SystemTest.java
+++ b/luni/src/test/java/libcore/java/lang/SystemTest.java
@@ -250,4 +250,14 @@
} catch (SecurityException expected) {
}
}
+
+ // http://b/34867424
+ public void testIcuPathIncludesTimeZoneOverride() {
+ String icuDataPath = System.getProperty("android.icu.impl.ICUBinary.dataPath");
+ String[] paths = icuDataPath.split(":");
+ assertEquals(2, paths.length);
+
+ assertTrue(paths[0].contains("/misc/zoneinfo/current/icu"));
+ assertTrue(paths[1].contains("/usr/icu"));
+ }
}
diff --git a/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java b/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
index 1e0c7b9..0f46460 100644
--- a/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
@@ -119,16 +119,21 @@
*/
public void testCountingProxy() throws Exception {
CountingProxy countingProxy = CountingProxy.start();
+ Socket socket = new Socket();
try {
- Proxy proxy = countingProxy.asProxy();
- assertEquals(Proxy.Type.HTTP, proxy.type());
- SocketAddress address = proxy.address();
- Socket socket = new Socket();
- socket.connect(address, /* timeout (msec) */ 10); // attempt one connection
- socket.close();
+ try {
+ Proxy proxy = countingProxy.asProxy();
+ assertEquals(Proxy.Type.HTTP, proxy.type());
+ SocketAddress address = proxy.address();
+ socket.connect(address, /* timeout (msec) */ 10); // attempt one connection
+ } finally {
+ int numConnections = countingProxy.shutdownAndGetConnectionCount();
+ assertEquals(1, numConnections);
+ }
} finally {
- int numConnections = countingProxy.shutdownAndGetConnectionCount();
- assertEquals(1, numConnections);
+ // Closing this socket *after* shutdownAndGetConnectionCount() ensures
+ // that the server thread had a chance to count the connection attempt.
+ socket.close();
}
}
diff --git a/luni/src/test/java/libcore/java/nio/channels/FileChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/FileChannelTest.java
index 8ecf72d..06286f0 100644
--- a/luni/src/test/java/libcore/java/nio/channels/FileChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/FileChannelTest.java
@@ -24,8 +24,20 @@
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.HashSet;
+import java.util.Set;
import libcore.io.IoUtils;
+import static java.nio.file.StandardOpenOption.READ;
+import static java.nio.file.StandardOpenOption.WRITE;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
public class FileChannelTest extends junit.framework.TestCase {
public void testReadOnlyByteArrays() throws Exception {
ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
@@ -255,4 +267,55 @@
return fc;
}
+
+ /**
+ * The test verifies that FileChannel#open(Path, Set<OpenOption>, FileAttribute ...) returns the
+ * same object returned by #newFileChannel(Path, Set<OpenOption>, FileAttribute ...) method
+ * in given Paths's FileSystemProvider.
+ */
+ public void test_open_Path_Set_FileAttributes() throws IOException {
+ Path mockPath = mock(Path.class);
+ FileSystem mockFileSystem = mock(FileSystem.class);
+ FileSystemProvider mockFileSystemProvider = mock(FileSystemProvider.class);
+ FileChannel mockFileChannel = mock(FileChannel.class);
+
+ FileAttribute mockFileAttribute1 = mock(FileAttribute.class);
+ FileAttribute mockFileAttribute2 = mock(FileAttribute.class);
+
+ Set<StandardOpenOption> standardOpenOptions = new HashSet<>();
+ standardOpenOptions.add(READ);
+ standardOpenOptions.add(WRITE);
+
+ when(mockPath.getFileSystem()).thenReturn(mockFileSystem);
+ when(mockFileSystem.provider()).thenReturn(mockFileSystemProvider);
+ when(mockFileSystemProvider.newFileChannel(mockPath, standardOpenOptions,
+ mockFileAttribute1, mockFileAttribute2)).thenReturn(mockFileChannel);
+
+ assertEquals(mockFileChannel, FileChannel.open(mockPath, standardOpenOptions,
+ mockFileAttribute1, mockFileAttribute2));
+ }
+
+ /**
+ * The test verifies that FileChannel#open(Path, OpenOption ...) returns the
+ * same object returned by #newFileChannel(Path, OpenOption ...) method
+ * in given Paths's FileSystemProvider.
+ */
+ public void test_open_Path_OpenOptions() throws IOException {
+
+ Path mockPath = mock(Path.class);
+ FileSystem mockFileSystem = mock(FileSystem.class);
+ FileSystemProvider mockFileSystemProvider = mock(FileSystemProvider.class);
+ FileChannel mockFileChannel = mock(FileChannel.class);
+
+ Set<StandardOpenOption> standardOpenOptions = new HashSet<>();
+ standardOpenOptions.add(READ);
+ standardOpenOptions.add(WRITE);
+
+ when(mockPath.getFileSystem()).thenReturn(mockFileSystem);
+ when(mockFileSystem.provider()).thenReturn(mockFileSystemProvider);
+ when(mockFileSystemProvider.newFileChannel(mockPath, standardOpenOptions))
+ .thenReturn(mockFileChannel);
+
+ assertEquals(mockFileChannel, FileChannel.open(mockPath, READ, WRITE));
+ }
}
diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
index 04be662..564f7c9 100644
--- a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
+++ b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
@@ -19,8 +19,12 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.NonReadableChannelException;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.DirectoryStream;
@@ -29,18 +33,34 @@
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.NotLinkException;
+import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
import java.nio.file.spi.FileSystemProvider;
+import java.util.EnumSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static java.nio.file.StandardOpenOption.APPEND;
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.READ;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import static libcore.java.nio.file.FilesSetup.DATA_FILE;
@@ -53,6 +73,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
+@RunWith(JUnitParamsRunner.class)
public class DefaultFileSystemProvider2Test {
@Rule
@@ -362,4 +383,249 @@
fail();
} catch (NullPointerException expected) {}
}
+
+ @Test
+ public void test_newFileChannel() throws IOException {
+ Set<OpenOption> openOptions = new HashSet<>();
+
+ // When file doesn't exist/
+ try {
+ // With CREATE & WRITE in OpenOptions.
+ openOptions.add(CREATE);
+ openOptions.add(WRITE);
+ provider.newFileChannel(filesSetup.getTestPath(), openOptions);
+ assertTrue(Files.exists(filesSetup.getTestPath()));
+ Files.delete(filesSetup.getTestPath());
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ try {
+ // With CREATE & APPEND in OpenOption.
+ assertFalse(Files.exists(filesSetup.getTestPath()));
+ openOptions.add(CREATE);
+ openOptions.add(APPEND);
+ provider.newFileChannel(filesSetup.getTestPath(), openOptions);
+ assertTrue(Files.exists(filesSetup.getTestPath()));
+ Files.delete(filesSetup.getTestPath());
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ // When file exists.
+ try {
+ FileChannel fc = provider.newFileChannel(filesSetup.getDataFilePath(), openOptions);
+ assertEquals(filesSetup.TEST_FILE_DATA, readFromFileChannel(fc));
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ try {
+ // When file exists and READ in OpenOptions.
+ openOptions.add(READ);
+ FileChannel fc = provider.newFileChannel(filesSetup.getDataFilePath(), openOptions);
+ assertEquals(filesSetup.TEST_FILE_DATA, readFromFileChannel(fc));
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ // Reading from a file opened with WRITE.
+ try {
+ openOptions.add(WRITE);
+ FileChannel fc = provider.newFileChannel(filesSetup.getDataFilePath(), openOptions);
+ assertEquals(filesSetup.TEST_FILE_DATA, readFromFileChannel(fc));
+ fail();
+ } catch (NonReadableChannelException expected) {
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ // Writing to an exiting file.
+ try {
+ openOptions.add(WRITE);
+ FileChannel fc = provider.newFileChannel(filesSetup.getDataFilePath(), openOptions);
+ writeToFileChannel(fc, filesSetup.TEST_FILE_DATA_2);
+ fc.close();
+ assertEquals(overlayString1OnString2(TEST_FILE_DATA_2, TEST_FILE_DATA),
+ readFromFile(filesSetup.getDataFilePath()));
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ // APPEND to an existing file.
+ try {
+ openOptions.add(WRITE);
+ openOptions.add(TRUNCATE_EXISTING);
+ FileChannel fc = provider.newFileChannel(filesSetup.getDataFilePath(), openOptions);
+ writeToFileChannel(fc, filesSetup.TEST_FILE_DATA_2);
+ fc.close();
+ assertEquals(TEST_FILE_DATA_2, readFromFile(filesSetup.getDataFilePath()));
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ // TRUNCATE an existing file.
+ try {
+ openOptions.add(WRITE);
+ openOptions.add(APPEND);
+ FileChannel fc = provider.newFileChannel(filesSetup.getDataFilePath(), openOptions);
+ writeToFileChannel(fc, filesSetup.TEST_FILE_DATA_2);
+ fc.close();
+ assertEquals(TEST_FILE_DATA + TEST_FILE_DATA_2, readFromFile(filesSetup.getDataFilePath()));
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+ }
+
+ @Test
+ @Parameters(method = "parameters_test_newFileChannel_NoSuchFileException")
+ public void test_newFileChannel_NoSuchFileException(Set<? extends OpenOption> openOptions)
+ throws IOException {
+ try {
+ provider.newFileChannel(filesSetup.getTestPath(), openOptions);
+ fail();
+ } catch (NoSuchFileException expected) {}
+ }
+
+ @SuppressWarnings("unused")
+ private Object[] parameters_test_newFileChannel_NoSuchFileException() {
+ return new Object[] {
+ new Object[] { EnumSet.noneOf(StandardOpenOption.class) },
+ new Object[] { EnumSet.of(READ) },
+ new Object[] { EnumSet.of(WRITE) },
+ new Object[] { EnumSet.of(TRUNCATE_EXISTING) },
+ new Object[] { EnumSet.of(APPEND) },
+ new Object[] { EnumSet.of(CREATE, READ) },
+ new Object[] { EnumSet.of(CREATE, TRUNCATE_EXISTING) },
+ new Object[] { EnumSet.of(CREATE, READ) },
+ };
+ }
+
+ @Test
+ public void test_newFileChannel_withFileAttributes() throws IOException {
+ Set<OpenOption> openOptions = new HashSet<>();
+ FileTime fileTime = FileTime.fromMillis(System.currentTimeMillis());
+ Files.setAttribute(filesSetup.getDataFilePath(), "basic:lastModifiedTime", fileTime);
+ FileAttribute<FileTime> unsupportedAttr = new MockFileAttribute<>(
+ "basic:lastModifiedTime", fileTime);
+
+ Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------");
+ FileAttribute<Set<PosixFilePermission>> supportedAttr =
+ PosixFilePermissions.asFileAttribute(perm);
+
+ try {
+ // When file doesn't exists and with OpenOption CREATE & WRITE.
+ openOptions.clear();
+ openOptions.add(CREATE);
+ openOptions.add(WRITE);
+ provider.newFileChannel(filesSetup.getTestPath(), openOptions, unsupportedAttr);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ try {
+ // With OpenOption CREATE & WRITE.
+ openOptions.clear();
+ openOptions.add(CREATE);
+ openOptions.add(WRITE);
+ provider.newFileChannel(filesSetup.getTestPath(), openOptions, supportedAttr);
+ assertEquals(supportedAttr.value(), Files.getAttribute(filesSetup.getTestPath(),
+ supportedAttr.name()));
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ // When file exists.
+ try {
+ provider.newFileChannel(filesSetup.getDataFilePath(), openOptions,
+ unsupportedAttr);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+
+ // When file exists. No change in permissions.
+ try {
+ Set<PosixFilePermission> originalPermissions= (Set<PosixFilePermission>)
+ Files.getAttribute(filesSetup.getDataFilePath(), supportedAttr.name());
+ FileChannel fc = provider.newFileChannel(filesSetup.getDataFilePath(), openOptions,
+ supportedAttr);
+ assertEquals(originalPermissions, Files.getAttribute(filesSetup.getDataFilePath(),
+ supportedAttr.name()));
+ } finally {
+ filesSetup.reset();
+ openOptions.clear();
+ }
+ }
+
+
+ @Test
+ public void test_newFileChannel_NPE() throws IOException {
+ try {
+ provider.newByteChannel(null, new HashSet<>(), new MockFileAttribute<>());
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ provider.newByteChannel(filesSetup.getTestPath(), null, new MockFileAttribute<>());
+ fail();
+ } catch (NullPointerException expected) {}
+
+ try {
+ provider.newByteChannel(filesSetup.getTestPath(), new HashSet<>(), null);
+ fail();
+ } catch (NullPointerException expected) {}
+ }
+
+ String readFromFileChannel(FileChannel fc) throws IOException {
+ ByteBuffer bb = ByteBuffer.allocate(20);
+ fc.read(bb);
+ return new String(bb.array(), "UTF-8").trim();
+ }
+
+ void writeToFileChannel(FileChannel fc, String data) throws IOException {
+ fc.write(ByteBuffer.wrap(data.getBytes()));
+ }
+
+ String overlayString1OnString2(String s1, String s2) {
+ return s1 + s2.substring(s1.length());
+ }
+
+ static class MockFileAttribute<T> implements FileAttribute {
+
+ String name;
+ T value;
+
+ MockFileAttribute() {
+ }
+
+ MockFileAttribute(String name, T value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public T value() {
+ return value;
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/security/PKCS12AttributeTest.java b/luni/src/test/java/libcore/java/security/PKCS12AttributeTest.java
index 62894d6..f4b2802 100644
--- a/luni/src/test/java/libcore/java/security/PKCS12AttributeTest.java
+++ b/luni/src/test/java/libcore/java/security/PKCS12AttributeTest.java
@@ -14,11 +14,12 @@
* limitations under the License
*/
-package java.security;
+package libcore.java.security;
import junit.framework.TestCase;
import java.io.IOException;
+import java.security.PKCS12Attribute;
import java.util.Arrays;
diff --git a/luni/src/test/java/libcore/java/security/PrincipalTest.java b/luni/src/test/java/libcore/java/security/PrincipalTest.java
index de20325..43a8e68 100644
--- a/luni/src/test/java/libcore/java/security/PrincipalTest.java
+++ b/luni/src/test/java/libcore/java/security/PrincipalTest.java
@@ -14,10 +14,11 @@
* limitations under the License
*/
-package java.security;
+package libcore.java.security;
import junit.framework.TestCase;
+import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
@@ -71,4 +72,4 @@
return this.name.equals(((PrincipalWithEqualityByName) other).getName());
}
}
-}
\ No newline at end of file
+}
diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java
index 22ebae5..04f4465 100644
--- a/ojluni/src/main/java/java/lang/System.java
+++ b/ojluni/src/main/java/java/lang/System.java
@@ -981,7 +981,8 @@
// is prioritized over the properties in ICUConfig.properties. The issue with using
// that is that it doesn't play well with jarjar and it needs complicated build rules
// to change its default value.
- p.put("android.icu.impl.ICUBinary.dataPath", getenv("ANDROID_ROOT") + "/usr/icu");
+ String icuDataPath = generateIcuDataPath();
+ p.put("android.icu.impl.ICUBinary.dataPath", icuDataPath);
parsePropertyAssignments(p, specialProperties());
@@ -1007,6 +1008,37 @@
return p;
}
+ private static String generateIcuDataPath() {
+ StringBuilder icuDataPathBuilder = new StringBuilder();
+ // ICU should first look in ANDROID_DATA. This is used for (optional) timezone data.
+ String dataIcuDataPath = getEnvironmentPath("ANDROID_DATA", "/misc/zoneinfo/current/icu");
+ if (dataIcuDataPath != null) {
+ icuDataPathBuilder.append(dataIcuDataPath);
+ }
+
+ // ICU should always look in ANDROID_ROOT.
+ String systemIcuDataPath = getEnvironmentPath("ANDROID_ROOT", "/usr/icu");
+ if (systemIcuDataPath != null) {
+ if (icuDataPathBuilder.length() > 0) {
+ icuDataPathBuilder.append(":");
+ }
+ icuDataPathBuilder.append(systemIcuDataPath);
+ }
+ return icuDataPathBuilder.toString();
+ }
+
+ /**
+ * Creates a path by combining the value of an environment variable with a relative path.
+ * Returns {@code null} if the environment variable is not set.
+ */
+ private static String getEnvironmentPath(String environmentVariable, String path) {
+ String variable = getenv(environmentVariable);
+ if (variable == null) {
+ return null;
+ }
+ return variable + path;
+ }
+
private static Properties initProperties() {
Properties p = new PropertiesWithNonOverrideableDefaults(unchangeableProps);
setDefaultChangeableProperties(p);
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
index cd5f70d..5b7ca6f 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
@@ -2186,23 +2186,23 @@
MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
int insCount = values.length;
Class<?>[] ptypes = insertArgumentsChecks(target, insCount, pos);
- if (insCount == 0) return target;
+ if (insCount == 0) {
+ return target;
+ }
- // BoundMethodHandle result = target.rebind();
- // for (int i = 0; i < insCount; i++) {
- // Object value = values[i];
- // Class<?> ptype = ptypes[pos+i];
- // if (ptype.isPrimitive()) {
- // result = insertArgumentPrimitive(result, pos, ptype, value);
- // } else {
- // value = ptype.cast(value); // throw CCE if needed
- // result = result.bindArgumentL(pos, value);
- // }
- // }
- // return result;
+ // Throw ClassCastExceptions early if we can't cast any of the provided values
+ // to the required type.
+ for (int i = 0; i < insCount; i++) {
+ final Class<?> ptype = ptypes[pos + i];
+ if (!ptype.isPrimitive()) {
+ ptypes[pos + i].cast(values[i]);
+ } else {
+ // Will throw a ClassCastException if something terrible happens.
+ values[i] = Wrapper.forPrimitiveType(ptype).convert(values[i], ptype);
+ }
+ }
- // TODO(narayan): Implement insertArguments, remove @hide.
- throw new UnsupportedOperationException("MethodHandles.insertArguments is not implemented");
+ return new Transformers.InsertArguments(target, pos, values);
}
// Android-changed: insertArgumentPrimitive is unused.
@@ -2421,30 +2421,12 @@
public static
MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
filterArgumentsCheckArity(target, pos, filters);
- MethodHandle adapter = target;
- int curPos = pos-1; // pre-incremented
- for (MethodHandle filter : filters) {
- curPos += 1;
- if (filter == null) continue; // ignore null elements of filters
- adapter = filterArgument(adapter, curPos, filter);
+
+ for (int i = 0; i < filters.length; ++i) {
+ filterArgumentChecks(target, i + pos, filters[i]);
}
- return adapter;
- }
- /*non-public*/ static
- MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
- filterArgumentChecks(target, pos, filter);
- // MethodType targetType = target.type();
- // MethodType filterType = filter.type();
- // BoundMethodHandle result = target.rebind();
- // Class<?> newParamType = filterType.parameterType(0);
- // LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType));
- // MethodType newType = targetType.changeParameterType(pos, newParamType);
- // result = result.copyWithExtendL(newType, lform, filter);
- // return result;
-
- // TODO(narayan): Implement filterArguments, remove @hide.
- throw new UnsupportedOperationException("MethodHandles.filterArgument is not implemented");
+ return new Transformers.FilterArguments(target, pos, filters);
}
private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) {
@@ -2573,21 +2555,7 @@
public static
MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) {
MethodType newType = collectArgumentsChecks(target, pos, filter);
- MethodType collectorType = filter.type();
-
- // BoundMethodHandle result = target.rebind();
- // LambdaForm lform;
- // if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) {
- // lform = result.editor().collectArgumentArrayForm(1 + pos, filter);
- // if (lform != null) {
- // return result.copyWith(newType, lform);
- // }
- // }
- // lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType());
- // return result.copyWithExtendL(newType, lform, filter);
-
- // TODO(narayan): Implement collectArguments, remove @hide.
- throw new UnsupportedOperationException("MethodHandles.collectArguments is not implemented");
+ return new Transformers.CollectArguments(target, filter, pos, newType);
}
private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
@@ -2764,8 +2732,7 @@
MethodType combinerType = combiner.type();
Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType);
- // TODO(narayan): Implement foldArguments, remove @hide.
- throw new UnsupportedOperationException("MethodHandles.foldArguments is not implemented");
+ return new Transformers.FoldArguments(target, combiner);
}
private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
diff --git a/ojluni/src/main/java/java/lang/invoke/Transformers.java b/ojluni/src/main/java/java/lang/invoke/Transformers.java
index a52d9d1..10ce855 100644
--- a/ojluni/src/main/java/java/lang/invoke/Transformers.java
+++ b/ojluni/src/main/java/java/lang/invoke/Transformers.java
@@ -29,6 +29,7 @@
import java.lang.reflect.Modifier;
import sun.invoke.util.Wrapper;
import sun.misc.Unsafe;
+import static dalvik.system.EmulatedStackFrame.StackFrameAccessor.copyNext;
/**
* @hide Public for testing only.
@@ -1053,7 +1054,6 @@
}
}
-
/**
* Implements MethodHandle.asSpreader / MethodHandles.spreadInvoker.
*/
@@ -1469,4 +1469,340 @@
targetFrame.copyReturnValueTo(callerFrame);
}
}
+
+ /*
+ * Implements MethodHandles.filterArguments.
+ */
+ static class FilterArguments extends Transformer {
+ /** The target handle. */
+ private final MethodHandle target;
+ /** Index of the first argument to filter */
+ private final int pos;
+ /** The list of filters to apply */
+ private final MethodHandle[] filters;
+
+ private final StackFrameWriter writer;
+ private final StackFrameReader reader;
+
+ private final StackFrameWriter filterWriter;
+ private final StackFrameReader filterReader;
+
+ FilterArguments(MethodHandle target, int pos, MethodHandle[] filters) {
+ super(deriveType(target, pos, filters));
+
+ this.target = target;
+ this.pos = pos;
+ this.filters = filters;
+
+ this.writer = new StackFrameWriter();
+ this.reader = new StackFrameReader();
+
+ this.filterReader = new StackFrameReader();
+ this.filterWriter = new StackFrameWriter();
+ }
+
+ private static MethodType deriveType(MethodHandle target, int pos, MethodHandle[] filters) {
+ final Class<?>[] filterArgs = new Class<?>[filters.length];
+ for (int i = 0; i < filters.length; ++i) {
+ filterArgs[i] = filters[i].type().parameterType(0);
+ }
+
+ return target.type().replaceParameterTypes(pos, pos + filters.length, filterArgs);
+ }
+
+ @Override
+ public void transform(EmulatedStackFrame stackFrame) throws Throwable {
+ reader.attach(stackFrame);
+
+ EmulatedStackFrame transformedFrame = EmulatedStackFrame.create(target.type());
+ writer.attach(transformedFrame);
+
+ final Class<?>[] ptypes = target.type().ptypes();
+ for (int i = 0; i < ptypes.length; ++i) {
+ // Check whether the current argument has a filter associated with it.
+ // If it has no filter, no further action need be taken.
+ final Class<?> ptype = ptypes[i];
+ final MethodHandle filter;
+ if (i < pos) {
+ filter = null;
+ } else if (i >= pos + filters.length) {
+ filter = null;
+ } else {
+ filter = filters[i - pos];
+ }
+
+ if (filter != null) {
+ // Note that filter.type() must be (ptype)ptype - this is checked before
+ // this transformer is created.
+ EmulatedStackFrame filterFrame = EmulatedStackFrame.create(filter.type());
+
+ // Copy the next argument from the stack frame to the filter frame.
+ filterWriter.attach(filterFrame);
+ copyNext(reader, filterWriter, filter.type().ptypes()[0]);
+
+ filter.invoke(filterFrame);
+
+ // Copy the argument back from the filter frame to the stack frame.
+ filterReader.attach(filterFrame);
+ filterReader.makeReturnValueAccessor();
+ copyNext(filterReader, writer, ptype);
+ } else {
+ // There's no filter associated with this frame, just copy the next argument
+ // over.
+ copyNext(reader, writer, ptype);
+ }
+ }
+
+ target.invoke(transformedFrame);
+ transformedFrame.copyReturnValueTo(stackFrame);
+ }
+ }
+
+ /**
+ * Implements MethodHandles.collectArguments.
+ */
+ static class CollectArguments extends Transformer {
+ private final MethodHandle target;
+ private final MethodHandle collector;
+ private final int pos;
+
+ /** The range of input arguments we copy to the collector. */
+ private final Range collectorRange;
+
+ /**
+ * The first range of arguments we copy to the target. These are arguments
+ * in the range [0, pos). Note that arg[pos] is the return value of the filter.
+ */
+ private final Range range1;
+
+ /**
+ * The second range of arguments we copy to the target. These are arguments in the range
+ * (pos, N], where N is the number of target arguments.
+ */
+ private final Range range2;
+
+ private final StackFrameReader reader;
+ private final StackFrameWriter writer;
+
+ private final int referencesOffset;
+ private final int stackFrameOffset;
+
+ CollectArguments(MethodHandle target, MethodHandle collector, int pos,
+ MethodType adapterType) {
+ super(adapterType);
+
+ this.target = target;
+ this.collector = collector;
+ this.pos = pos;
+
+ final int numFilterArgs = collector.type().parameterCount();
+ final int numAdapterArgs = type().parameterCount();
+ collectorRange = Range.of(type(), pos, pos + numFilterArgs);
+
+ range1 = Range.of(type(), 0, pos);
+ if (pos + numFilterArgs < numAdapterArgs) {
+ this.range2 = Range.of(type(), pos + numFilterArgs, numAdapterArgs);
+ } else {
+ this.range2 = null;
+ }
+
+ reader = new StackFrameReader();
+ writer = new StackFrameWriter();
+
+ // Calculate the number of primitive bytes (or references) we copy to the
+ // target frame based on the return value of the combiner.
+ final Class<?> collectorRType = collector.type().rtype();
+ if (collectorRType == void.class) {
+ stackFrameOffset = 0;
+ referencesOffset = 0;
+ } else if (collectorRType.isPrimitive()) {
+ stackFrameOffset = EmulatedStackFrame.getSize(collectorRType);
+ referencesOffset = 0;
+ } else {
+ stackFrameOffset = 0;
+ referencesOffset = 1;
+ }
+ }
+
+ @Override
+ public void transform(EmulatedStackFrame stackFrame) throws Throwable {
+ // First invoke the collector.
+ EmulatedStackFrame filterFrame = EmulatedStackFrame.create(collector.type());
+ stackFrame.copyRangeTo(filterFrame, collectorRange, 0, 0);
+ collector.invoke(filterFrame);
+
+ // Start constructing the target frame.
+ EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
+ stackFrame.copyRangeTo(targetFrame, range1, 0, 0);
+
+ // If one of these offsets is not zero, we have a return value to copy.
+ if (referencesOffset != 0 || stackFrameOffset != 0) {
+ reader.attach(filterFrame).makeReturnValueAccessor();
+ writer.attach(targetFrame, pos, range1.numReferences, range1.numBytes);
+ copyNext(reader, writer, target.type().ptypes()[0]);
+ }
+
+ if (range2 != null) {
+ stackFrame.copyRangeTo(targetFrame, range2,
+ range1.numReferences + referencesOffset,
+ range2.numBytes + stackFrameOffset);
+ }
+
+ target.invoke(targetFrame);
+ targetFrame.copyReturnValueTo(stackFrame);
+ }
+ }
+
+ /**
+ * Implements MethodHandles.foldArguments.
+ */
+ static class FoldArguments extends Transformer {
+ private final MethodHandle target;
+ private final MethodHandle combiner;
+
+ private final Range combinerArgs;
+ private final Range targetArgs;
+
+ private final StackFrameReader reader;
+ private final StackFrameWriter writer;
+
+ private final int referencesOffset;
+ private final int stackFrameOffset;
+
+ FoldArguments(MethodHandle target, MethodHandle combiner) {
+ super(deriveType(target, combiner));
+
+ this.target = target;
+ this.combiner = combiner;
+
+ combinerArgs = Range.all(combiner.type());
+ targetArgs = Range.all(type());
+
+ reader = new StackFrameReader();
+ writer = new StackFrameWriter();
+
+ final Class<?> combinerRType = combiner.type().rtype();
+ if (combinerRType == void.class) {
+ stackFrameOffset = 0;
+ referencesOffset = 0;
+ } else if (combinerRType.isPrimitive()) {
+ stackFrameOffset = EmulatedStackFrame.getSize(combinerRType);
+ referencesOffset = 0;
+ } else {
+ stackFrameOffset = 0;
+ referencesOffset = 1;
+ }
+ }
+
+ @Override
+ public void transform(EmulatedStackFrame stackFrame) throws Throwable {
+ // First construct the combiner frame and invoke it.
+ EmulatedStackFrame combinerFrame = EmulatedStackFrame.create(combiner.type());
+ stackFrame.copyRangeTo(combinerFrame, combinerArgs, 0, 0);
+ combiner.invoke(combinerFrame);
+
+ // Create the stack frame for the target.
+ EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
+
+ // If one of these offsets is not zero, we have a return value to copy.
+ if (referencesOffset != 0 || stackFrameOffset != 0) {
+ reader.attach(combinerFrame).makeReturnValueAccessor();
+ writer.attach(targetFrame);
+ copyNext(reader, writer, target.type().ptypes()[0]);
+ }
+
+ stackFrame.copyRangeTo(targetFrame, targetArgs, referencesOffset, stackFrameOffset);
+ target.invoke(targetFrame);
+
+ targetFrame.copyReturnValueTo(stackFrame);
+ }
+
+ private static MethodType deriveType(MethodHandle target, MethodHandle combiner) {
+ if (combiner.type().rtype() == void.class) {
+ return target.type();
+ }
+
+ return target.type().dropParameterTypes(0, 1);
+ }
+ }
+
+ /**
+ * Implements MethodHandles.insertArguments.
+ */
+ static class InsertArguments extends Transformer {
+ private final MethodHandle target;
+ private final int pos;
+ private final Object[] values;
+
+ private final Range range1;
+ private final Range range2;
+ private final StackFrameWriter writer;
+
+ InsertArguments(MethodHandle target, int pos, Object[] values) {
+ super(target.type().dropParameterTypes(pos, pos + values.length));
+ this.target = target;
+ this.pos = pos;
+ this.values = values;
+
+ final MethodType type = type();
+ range1 = EmulatedStackFrame.Range.of(type, 0, pos);
+ range2 = Range.of(type, pos, type.parameterCount());
+
+ writer = new StackFrameWriter();
+ }
+
+ @Override
+ public void transform(EmulatedStackFrame stackFrame) throws Throwable {
+ EmulatedStackFrame calleeFrame = EmulatedStackFrame.create(target.type());
+
+ // Copy all arguments before |pos|.
+ stackFrame.copyRangeTo(calleeFrame, range1, 0, 0);
+
+ // Attach a stack frame writer so that we can copy the next |values.length|
+ // arguments.
+ writer.attach(calleeFrame, pos, range1.numReferences, range1.numBytes);
+
+ // Copy all the arguments supplied in |values|.
+ int referencesCopied = 0;
+ int bytesCopied = 0;
+ final Class<?>[] ptypes = target.type().ptypes();
+ for (int i = 0; i < values.length; ++i) {
+ final Class<?> ptype = ptypes[i + pos];
+ if (ptype.isPrimitive()) {
+ if (ptype == boolean.class) {
+ writer.putNextBoolean((boolean) values[i]);
+ } else if (ptype == byte.class) {
+ writer.putNextByte((byte) values[i]);
+ } else if (ptype == char.class) {
+ writer.putNextChar((char) values[i]);
+ } else if (ptype == short.class) {
+ writer.putNextShort((short) values[i]);
+ } else if (ptype == int.class) {
+ writer.putNextInt((int) values[i]);
+ } else if (ptype == long.class) {
+ writer.putNextLong((long) values[i]);
+ } else if (ptype == float.class) {
+ writer.putNextFloat((float) values[i]);
+ } else if (ptype == double.class) {
+ writer.putNextDouble((double) values[i]);
+ }
+
+ bytesCopied += EmulatedStackFrame.getSize(ptype);
+ } else {
+ writer.putNextReference(values[i], ptype);
+ referencesCopied++;
+ }
+ }
+
+ // Copy all remaining arguments.
+ if (range2 != null) {
+ stackFrame.copyRangeTo(calleeFrame, range2,
+ range1.numReferences + referencesCopied,
+ range1.numBytes + bytesCopied);
+ }
+
+ target.invoke(calleeFrame);
+ calleeFrame.copyReturnValueTo(stackFrame);
+ }
+ }
}
diff --git a/ojluni/src/main/java/java/util/Calendar.java b/ojluni/src/main/java/java/util/Calendar.java
index 2a10aee..60c1c97 100644
--- a/ojluni/src/main/java/java/util/Calendar.java
+++ b/ojluni/src/main/java/java/util/Calendar.java
@@ -2034,6 +2034,11 @@
* @since 1.6
*/
public String getDisplayName(int field, int style, Locale locale) {
+ // Android-changed: Android has traditionally treated ALL_STYLES as SHORT, even though
+ // it's not documented to be a valid value for style.
+ if (style == ALL_STYLES) {
+ style = SHORT;
+ }
if (!checkDisplayNameParams(field, style, SHORT, NARROW_FORMAT, locale,
ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
return null;
@@ -2174,6 +2179,10 @@
baseStyle < minStyle || baseStyle > maxStyle) {
throw new IllegalArgumentException();
}
+ // Android-changed: 3 is not a valid base style (1, 2 and 4 are, though), throw if used.
+ if (baseStyle == 3) {
+ throw new IllegalArgumentException();
+ }
if (locale == null) {
throw new NullPointerException();
}
diff --git a/ojluni/src/main/java/java/util/Formatter.java b/ojluni/src/main/java/java/util/Formatter.java
index d6d8502..ca1b990 100644
--- a/ojluni/src/main/java/java/util/Formatter.java
+++ b/ojluni/src/main/java/java/util/Formatter.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -48,6 +48,13 @@
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalQueries;
import libcore.icu.LocaleData;
import sun.misc.FpUtils;
@@ -124,7 +131,7 @@
* import static java.util.Calendar.*;
*
* Calendar c = new GregorianCalendar(1995, MAY, 23);
- * String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
+ * String s = String.format("Duke's Birthday: %1$tb %1$te, %1$tY", c);
* // -> s == "Duke's Birthday: May 23, 1995"
* </pre></blockquote>
*
@@ -183,7 +190,7 @@
* <p> The optional <i>flags</i> is a set of characters that modify the output
* format. The set of valid flags depends on the conversion.
*
- * <p> The optional <i>width</i> is a non-negative decimal integer indicating
+ * <p> The optional <i>width</i> is a positive decimal integer indicating
* the minimum number of characters to be written to the output.
*
* <p> The optional <i>precision</i> is a non-negative decimal integer usually
@@ -246,7 +253,7 @@
* <li> <b>Integral</b> - may be applied to Java integral types: {@code byte},
* {@link Byte}, {@code short}, {@link Short}, {@code int} and {@link
* Integer}, {@code long}, {@link Long}, and {@link java.math.BigInteger
- * BigInteger}
+ * BigInteger} (but not {@code char} or {@link Character})
*
* <li><b>Floating Point</b> - may be applied to Java floating-point types:
* {@code float}, {@link Float}, {@code double}, {@link Double}, and {@link
@@ -255,8 +262,8 @@
* </ol>
*
* <li> <b>Date/Time</b> - may be applied to Java types which are capable of
- * encoding a date or time: {@code long}, {@link Long}, {@link Calendar}, and
- * {@link Date}.
+ * encoding a date or time: {@code long}, {@link Long}, {@link Calendar},
+ * {@link Date} and {@link TemporalAccessor TemporalAccessor}
*
* <li> <b>Percent</b> - produces a literal {@code '%'}
* (<tt>'\u0025'</tt>)
@@ -337,7 +344,9 @@
* <tr><td valign="top">{@code 'a'}, {@code 'A'}
* <td valign="top"> floating point
* <td> The result is formatted as a hexadecimal floating-point number with
- * a significand and an exponent
+ * a significand and an exponent. This conversion is <b>not</b> supported
+ * for the {@code BigDecimal} type despite the latter's being in the
+ * <i>floating point</i> argument category.
*
* <tr><td valign="top">{@code 't'}, {@code 'T'}
* <td valign="top"> date/time
@@ -617,12 +626,11 @@
* <p> For general argument types, the precision is the maximum number of
* characters to be written to the output.
*
- * <p> For the floating-point conversions {@code 'e'}, {@code 'E'}, and
- * {@code 'f'} the precision is the number of digits after the decimal
- * separator. If the conversion is {@code 'g'} or {@code 'G'}, then the
+ * <p> For the floating-point conversions {@code 'a'}, {@code 'A'}, {@code 'e'},
+ * {@code 'E'}, and {@code 'f'} the precision is the number of digits after the
+ * radix point. If the conversion is {@code 'g'} or {@code 'G'}, then the
* precision is the total number of digits in the resulting magnitude after
- * rounding. If the conversion is {@code 'a'} or {@code 'A'}, then the
- * precision must not be specified.
+ * rounding.
*
* <p> For character, integral, and date/time argument types and the percent
* and line separator conversions, the precision is not applicable; if a
@@ -832,7 +840,7 @@
*
* <p> Numeric types will be formatted according to the following algorithm:
*
- * <p><b><a name="l10n algorithm"> Number Localization Algorithm</a></b>
+ * <p><b><a name="L10nAlgorithm"> Number Localization Algorithm</a></b>
*
* <p> After digits are obtained for the integer part, fractional part, and
* exponent (as appropriate for the data type), the following transformation
@@ -851,7 +859,7 @@
* substituted.
*
* <li> If the {@code ','} (<tt>'\u002c'</tt>)
- * <a name="l10n group">flag</a> is given, then the locale-specific {@linkplain
+ * <a name="L10nGroup">flag</a> is given, then the locale-specific {@linkplain
* java.text.DecimalFormatSymbols#getGroupingSeparator grouping separator} is
* inserted by scanning the integer part of the string from least significant
* to most significant digits and inserting a separator at intervals defined by
@@ -891,9 +899,9 @@
* <table cellpadding=5 summary="IntConv">
*
* <tr><td valign="top"> {@code 'd'}
- * <td valign="top"> <tt>'\u0054'</tt>
+ * <td valign="top"> <tt>'\u0064'</tt>
* <td> Formats the argument as a decimal integer. The <a
- * href="#l10n algorithm">localization algorithm</a> is applied.
+ * href="#L10nAlgorithm">localization algorithm</a> is applied.
*
* <p> If the {@code '0'} flag is given and the value is negative, then
* the zero padding will occur after the sign.
@@ -919,7 +927,7 @@
* <p> If the {@code '0'} flag is given then the output will be padded
* with leading zeros to the field width following any indication of sign.
*
- * <p> If {@code '('}, {@code '+'}, '  ', or {@code ','} flags
+ * <p> If {@code '('}, {@code '+'}, ' ', or {@code ','} flags
* are given then a {@link FormatFlagsConversionMismatchException} will be
* thrown.
*
@@ -1002,7 +1010,7 @@
* <td valign="top"> <tt>'\u002c'</tt>
* <td> Requires the output to include the locale-specific {@linkplain
* java.text.DecimalFormatSymbols#getGroupingSeparator group separators} as
- * described in the <a href="#l10n group">"group" section</a> of the
+ * described in the <a href="#L10nGroup">"group" section</a> of the
* localization algorithm.
*
* <tr><td valign="top"> {@code '('}
@@ -1049,9 +1057,9 @@
* <table cellpadding=5 summary="BIntConv">
*
* <tr><td valign="top"> {@code 'd'}
- * <td valign="top"> <tt>'\u0054'</tt>
+ * <td valign="top"> <tt>'\u0064'</tt>
* <td> Requires the output to be formatted as a decimal integer. The <a
- * href="#l10n algorithm">localization algorithm</a> is applied.
+ * href="#L10nAlgorithm">localization algorithm</a> is applied.
*
* <p> If the {@code '#'} flag is given {@link
* FormatFlagsConversionMismatchException} will be thrown.
@@ -1146,7 +1154,7 @@
* <td valign="top"> <tt>'\u0065'</tt>
* <td> Requires the output to be formatted using <a
* name="scientific">computerized scientific notation</a>. The <a
- * href="#l10n algorithm">localization algorithm</a> is applied.
+ * href="#L10nAlgorithm">localization algorithm</a> is applied.
*
* <p> The formatting of the magnitude <i>m</i> depends upon its value.
*
@@ -1159,7 +1167,7 @@
*
* <p> Otherwise, the result is a string that represents the sign and
* magnitude (absolute value) of the argument. The formatting of the sign
- * is described in the <a href="#l10n algorithm">localization
+ * is described in the <a href="#L10nAlgorithm">localization
* algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
* value.
*
@@ -1201,7 +1209,7 @@
* <tr><td valign="top"> {@code 'g'}
* <td valign="top"> <tt>'\u0067'</tt>
* <td> Requires the output to be formatted in general scientific notation
- * as described below. The <a href="#l10n algorithm">localization
+ * as described below. The <a href="#L10nAlgorithm">localization
* algorithm</a> is applied.
*
* <p> After rounding for the precision, the formatting of the resulting
@@ -1230,12 +1238,12 @@
* <tr><td valign="top"> {@code 'f'}
* <td valign="top"> <tt>'\u0066'</tt>
* <td> Requires the output to be formatted using <a name="decimal">decimal
- * format</a>. The <a href="#l10n algorithm">localization algorithm</a> is
+ * format</a>. The <a href="#L10nAlgorithm">localization algorithm</a> is
* applied.
*
* <p> The result is a string that represents the sign and magnitude
* (absolute value) of the argument. The formatting of the sign is
- * described in the <a href="#l10n algorithm">localization
+ * described in the <a href="#L10nAlgorithm">localization
* algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
* value.
*
@@ -1291,14 +1299,21 @@
* of the significand as a fraction. The exponent is represented by
* {@code 'p'} (<tt>'\u0070'</tt>) followed by a decimal string of the
* unbiased exponent as if produced by invoking {@link
- * Integer#toString(int) Integer.toString} on the exponent value.
+ * Integer#toString(int) Integer.toString} on the exponent value. If the
+ * precision is specified, the value is rounded to the given number of
+ * hexadecimal digits.
*
* <li> If <i>m</i> is a {@code double} value with a subnormal
- * representation then the significand is represented by the characters
- * {@code '0x0.'} followed by the hexadecimal representation of the rest
- * of the significand as a fraction. The exponent is represented by
- * {@code 'p-1022'}. Note that there must be at least one nonzero digit
- * in a subnormal significand.
+ * representation then, unless the precision is specified to be in the range
+ * 1 through 12, inclusive, the significand is represented by the characters
+ * {@code '0x0.'} followed by the hexadecimal representation of the rest of
+ * the significand as a fraction, and the exponent represented by
+ * {@code 'p-1022'}. If the precision is in the interval
+ * [1, 12], the subnormal value is normalized such that it
+ * begins with the characters {@code '0x1.'}, rounded to the number of
+ * hexadecimal digits of precision, and the exponent adjusted
+ * accordingly. Note that there must be at least one nonzero digit in a
+ * subnormal significand.
*
* </ul>
*
@@ -1361,7 +1376,7 @@
* {@code 1}.
*
* <p> If the conversion is {@code 'a'} or {@code 'A'}, then the precision
- * is the number of hexadecimal digits after the decimal separator. If the
+ * is the number of hexadecimal digits after the radix point. If the
* precision is not provided, then all of the digits as returned by {@link
* Double#toHexString(double)} will be output.
*
@@ -1376,7 +1391,7 @@
* <td valign="top"> <tt>'\u0065'</tt>
* <td> Requires the output to be formatted using <a
* name="bscientific">computerized scientific notation</a>. The <a
- * href="#l10n algorithm">localization algorithm</a> is applied.
+ * href="#L10nAlgorithm">localization algorithm</a> is applied.
*
* <p> The formatting of the magnitude <i>m</i> depends upon its value.
*
@@ -1385,7 +1400,7 @@
*
* <p> Otherwise, the result is a string that represents the sign and
* magnitude (absolute value) of the argument. The formatting of the sign
- * is described in the <a href="#l10n algorithm">localization
+ * is described in the <a href="#L10nAlgorithm">localization
* algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
* value.
*
@@ -1422,7 +1437,7 @@
* <tr><td valign="top"> {@code 'g'}
* <td valign="top"> <tt>'\u0067'</tt>
* <td> Requires the output to be formatted in general scientific notation
- * as described below. The <a href="#l10n algorithm">localization
+ * as described below. The <a href="#L10nAlgorithm">localization
* algorithm</a> is applied.
*
* <p> After rounding for the precision, the formatting of the resulting
@@ -1451,12 +1466,12 @@
* <tr><td valign="top"> {@code 'f'}
* <td valign="top"> <tt>'\u0066'</tt>
* <td> Requires the output to be formatted using <a name="bdecimal">decimal
- * format</a>. The <a href="#l10n algorithm">localization algorithm</a> is
+ * format</a>. The <a href="#L10nAlgorithm">localization algorithm</a> is
* applied.
*
* <p> The result is a string that represents the sign and magnitude
* (absolute value) of the argument. The formatting of the sign is
- * described in the <a href="#l10n algorithm">localization
+ * described in the <a href="#L10nAlgorithm">localization
* algorithm</a>. The formatting of the magnitude <i>m</i> depends upon its
* value.
*
@@ -1492,7 +1507,7 @@
* <h4><a name="ddt">Date/Time</a></h4>
*
* <p> This conversion may be applied to {@code long}, {@link Long}, {@link
- * Calendar}, and {@link Date}.
+ * Calendar}, {@link Date} and {@link TemporalAccessor TemporalAccessor}
*
* <table cellpadding=5 summary="DTConv">
*
@@ -1715,7 +1730,7 @@
* conversions</a> applies. If the {@code '#'} flag is given, then a {@link
* FormatFlagsConversionMismatchException} will be thrown.
*
- * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
+ * <p> The width is the minimum number of characters to
* be written to the output. If the length of the converted value is less than
* the {@code width} then the output will be padded by spaces
* (<tt>'\u0020'</tt>) until the total number of characters equals width.
@@ -1735,7 +1750,7 @@
* <tr><td valign="top">{@code '%'}
* <td> The result is a literal {@code '%'} (<tt>'\u0025'</tt>)
*
- * <p> The <a name="dtWidth">width</a> is the minimum number of characters to
+ * <p> The width is the minimum number of characters to
* be written to the output including the {@code '%'}. If the length of the
* converted value is less than the {@code width} then the output will be
* padded by spaces (<tt>'\u0020'</tt>) until the total number of
@@ -1894,7 +1909,8 @@
* which may be retrieved by invoking {@link #out out()} and whose
* current content may be converted into a string by invoking {@link
* #toString toString()}. The locale used is the {@linkplain
- * Locale#getDefault() default locale} for this instance of the Java
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
* virtual machine.
*/
public Formatter() {
@@ -1904,8 +1920,10 @@
/**
* Constructs a new formatter with the specified destination.
*
- * <p> The locale used is the {@linkplain Locale#getDefault() default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* @param a
* Destination for the formatted output. If {@code a} is
@@ -1955,8 +1973,10 @@
* java.nio.charset.Charset#defaultCharset() default charset} for this
* instance of the Java virtual machine.
*
- * <p> The locale used is the {@linkplain Locale#getDefault() default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* @param fileName
* The name of the file to use as the destination of this
@@ -1983,8 +2003,10 @@
/**
* Constructs a new formatter with the specified file name and charset.
*
- * <p> The locale used is the {@linkplain Locale#getDefault default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* @param fileName
* The name of the file to use as the destination of this
@@ -2062,8 +2084,10 @@
* java.nio.charset.Charset#defaultCharset() default charset} for this
* instance of the Java virtual machine.
*
- * <p> The locale used is the {@linkplain Locale#getDefault() default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* @param file
* The file to use as the destination of this formatter. If the
@@ -2090,8 +2114,10 @@
/**
* Constructs a new formatter with the specified file and charset.
*
- * <p> The locale used is the {@linkplain Locale#getDefault default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* @param file
* The file to use as the destination of this formatter. If the
@@ -2165,8 +2191,10 @@
/**
* Constructs a new formatter with the specified print stream.
*
- * <p> The locale used is the {@linkplain Locale#getDefault() default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* <p> Characters are written to the given {@link java.io.PrintStream
* PrintStream} object and are therefore encoded using that object's
@@ -2187,8 +2215,10 @@
* java.nio.charset.Charset#defaultCharset() default charset} for this
* instance of the Java virtual machine.
*
- * <p> The locale used is the {@linkplain Locale#getDefault() default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* @param os
* The output stream to use as the destination of this formatter.
@@ -2203,8 +2233,10 @@
* Constructs a new formatter with the specified output stream and
* charset.
*
- * <p> The locale used is the {@linkplain Locale#getDefault default
- * locale} for this instance of the Java virtual machine.
+ * <p> The locale used is the {@linkplain
+ * Locale#getDefault(Locale.Category) default locale} for
+ * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java
+ * virtual machine.
*
* @param os
* The output stream to use as the destination of this formatter.
@@ -2504,6 +2536,7 @@
return this;
}
+ // Android-changed BEGIN: changed parse() to manual parsing instead of regex.
/**
* Finds format specifiers in the format string.
*/
@@ -2633,6 +2666,7 @@
return cursor;
}
}
+ // Android-changed END: changed parse() to manual parsing instead of regex.
private interface FormatString {
int index();
@@ -2649,7 +2683,20 @@
public String toString() { return s; }
}
- public enum BigDecimalLayoutForm { SCIENTIFIC, DECIMAL_FLOAT };
+ /**
+ * Enum for {@code BigDecimal} formatting.
+ */
+ public enum BigDecimalLayoutForm {
+ /**
+ * Format the {@code BigDecimal} in computerized scientific notation.
+ */
+ SCIENTIFIC,
+
+ /**
+ * Format the {@code BigDecimal} as a decimal number.
+ */
+ DECIMAL_FLOAT
+ };
private class FormatSpecifier implements FormatString {
private int index = -1;
@@ -2662,6 +2709,7 @@
private int index(String s) {
if (s != null) {
try {
+ // Android-changed: FormatSpecifierParser passes in correct String.
index = Integer.parseInt(s);
} catch (NumberFormatException x) {
assert(false);
@@ -2741,6 +2789,7 @@
return c;
}
+ // Android-changed: FormatSpecifierParser passes in the values instead of a Matcher.
FormatSpecifier(String indexStr, String flagsStr, String widthStr,
String precisionStr, String tTStr, String convStr) {
int idx = 1;
@@ -2865,8 +2914,11 @@
cal = Calendar.getInstance(l == null ? Locale.US : l);
cal.setTime((Date)arg);
} else if (arg instanceof Calendar) {
- cal = (Calendar) ((Calendar)arg).clone();
+ cal = (Calendar) ((Calendar) arg).clone();
cal.setLenient(true);
+ } else if (arg instanceof TemporalAccessor) {
+ print((TemporalAccessor) arg, c, l);
+ return;
} else {
failConversion(c, arg);
}
@@ -2945,7 +2997,7 @@
if (precision != -1 && precision < s.length())
s = s.substring(0, precision);
if (f.contains(Flags.UPPERCASE)) {
- // Always uppercase strings according to the provided locale.
+ // Android-changed: Use provided locale instead of default, if it is non-null.
s = s.toUpperCase(l != null ? l : Locale.getDefault());
}
a.append(justify(s));
@@ -3299,8 +3351,8 @@
int prec = (precision == -1 ? 6 : precision);
FormattedFloatingDecimal fd
- = FormattedFloatingDecimal.valueOf(value, prec,
- FormattedFloatingDecimal.Form.SCIENTIFIC);
+ = FormattedFloatingDecimal.valueOf(value, prec,
+ FormattedFloatingDecimal.Form.SCIENTIFIC);
char[] mant = addZeros(fd.getMantissa(), prec);
@@ -3317,6 +3369,7 @@
newW = adjustWidth(width - exp.length - 1, f, neg);
localizedMagnitude(sb, mant, f, newW, l);
+ // Android-changed: Use localized exponent separator for %e.
Locale separatorLocale = (l != null) ? l : Locale.getDefault();
LocaleData localeData = LocaleData.get(separatorLocale);
sb.append(f.contains(Flags.UPPERCASE) ?
@@ -3439,30 +3492,6 @@
}
}
- private char[] mantissa(char[] v, int len) {
- int i;
- for (i = 0; i < len; i++) {
- if (v[i] == 'e')
- break;
- }
- char[] tmp = new char[i];
- System.arraycopy(v, 0, tmp, 0, i);
- return tmp;
- }
-
- private char[] exponent(char[] v, int len) {
- int i;
- for (i = len - 1; i >= 0; i--) {
- if (v[i] == 'e')
- break;
- }
- if (i == -1)
- return null;
- char[] tmp = new char[len - i - 1];
- System.arraycopy(v, i + 1, tmp, 0, len - i - 1);
- return tmp;
- }
-
// Add zeros to the requested precision.
private char[] addZeros(char[] v, int prec) {
// Look for the dot. If we don't find one, the we'll need to add
@@ -3505,24 +3534,24 @@
// Method assumes that d > 0.
private String hexDouble(double d, int prec) {
// Let Double.toHexString handle simple cases
- if(!FpUtils.isFinite(d) || d == 0.0 || prec == 0 || prec >= 13)
+ if(!Double.isFinite(d) || d == 0.0 || prec == 0 || prec >= 13)
// remove "0x"
return Double.toHexString(d).substring(2);
else {
assert(prec >= 1 && prec <= 12);
- int exponent = FpUtils.getExponent(d);
+ int exponent = Math.getExponent(d);
boolean subnormal
= (exponent == DoubleConsts.MIN_EXPONENT - 1);
// If this is subnormal input so normalize (could be faster to
// do as integer operation).
if (subnormal) {
- scaleUp = FpUtils.scalb(1.0, 54);
+ scaleUp = Math.scalb(1.0, 54);
d *= scaleUp;
// Calculate the exponent. This is not just exponent + 54
// since the former is not the normalized exponent.
- exponent = FpUtils.getExponent(d);
+ exponent = Math.getExponent(d);
assert exponent >= DoubleConsts.MIN_EXPONENT &&
exponent <= DoubleConsts.MAX_EXPONENT: exponent;
}
@@ -3916,7 +3945,6 @@
Locale l)
throws IOException
{
- assert(width == -1);
if (sb == null)
sb = new StringBuilder();
switch (c) {
@@ -4122,6 +4150,242 @@
return sb;
}
+ private void print(TemporalAccessor t, char c, Locale l) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ print(sb, t, c, l);
+ // justify based on width
+ String s = justify(sb.toString());
+ if (f.contains(Flags.UPPERCASE))
+ s = s.toUpperCase();
+ a.append(s);
+ }
+
+ private Appendable print(StringBuilder sb, TemporalAccessor t, char c,
+ Locale l) throws IOException {
+ if (sb == null)
+ sb = new StringBuilder();
+ try {
+ switch (c) {
+ case DateTime.HOUR_OF_DAY_0: { // 'H' (00 - 23)
+ int i = t.get(ChronoField.HOUR_OF_DAY);
+ sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l));
+ break;
+ }
+ case DateTime.HOUR_OF_DAY: { // 'k' (0 - 23) -- like H
+ int i = t.get(ChronoField.HOUR_OF_DAY);
+ sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l));
+ break;
+ }
+ case DateTime.HOUR_0: { // 'I' (01 - 12)
+ int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM);
+ sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l));
+ break;
+ }
+ case DateTime.HOUR: { // 'l' (1 - 12) -- like I
+ int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM);
+ sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l));
+ break;
+ }
+ case DateTime.MINUTE: { // 'M' (00 - 59)
+ int i = t.get(ChronoField.MINUTE_OF_HOUR);
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, i, flags, 2, l));
+ break;
+ }
+ case DateTime.NANOSECOND: { // 'N' (000000000 - 999999999)
+ int i = t.get(ChronoField.MILLI_OF_SECOND) * 1000000;
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, i, flags, 9, l));
+ break;
+ }
+ case DateTime.MILLISECOND: { // 'L' (000 - 999)
+ int i = t.get(ChronoField.MILLI_OF_SECOND);
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, i, flags, 3, l));
+ break;
+ }
+ case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?)
+ long i = t.getLong(ChronoField.INSTANT_SECONDS) * 1000L +
+ t.getLong(ChronoField.MILLI_OF_SECOND);
+ Flags flags = Flags.NONE;
+ sb.append(localizedMagnitude(null, i, flags, width, l));
+ break;
+ }
+ case DateTime.AM_PM: { // 'p' (am or pm)
+ // Calendar.AM = 0, Calendar.PM = 1, LocaleElements defines upper
+ String[] ampm = { "AM", "PM" };
+ if (l != null && l != Locale.US) {
+ DateFormatSymbols dfs = DateFormatSymbols.getInstance(l);
+ ampm = dfs.getAmPmStrings();
+ }
+ String s = ampm[t.get(ChronoField.AMPM_OF_DAY)];
+ sb.append(s.toLowerCase(l != null ? l : Locale.US));
+ break;
+ }
+ case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
+ long i = t.getLong(ChronoField.INSTANT_SECONDS);
+ Flags flags = Flags.NONE;
+ sb.append(localizedMagnitude(null, i, flags, width, l));
+ break;
+ }
+ case DateTime.SECOND: { // 'S' (00 - 60 - leap second)
+ int i = t.get(ChronoField.SECOND_OF_MINUTE);
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, i, flags, 2, l));
+ break;
+ }
+ case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus?
+ int i = t.get(ChronoField.OFFSET_SECONDS);
+ boolean neg = i < 0;
+ sb.append(neg ? '-' : '+');
+ if (neg)
+ i = -i;
+ int min = i / 60;
+ // combine minute and hour into a single integer
+ int offset = (min / 60) * 100 + (min % 60);
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, offset, flags, 4, l));
+ break;
+ }
+ case DateTime.ZONE: { // 'Z' (symbol)
+ ZoneId zid = t.query(TemporalQueries.zone());
+ if (zid == null) {
+ throw new IllegalFormatConversionException(c, t.getClass());
+ }
+ if (!(zid instanceof ZoneOffset) &&
+ t.isSupported(ChronoField.INSTANT_SECONDS)) {
+ Instant instant = Instant.from(t);
+ sb.append(TimeZone.getTimeZone(zid.getId())
+ .getDisplayName(zid.getRules().isDaylightSavings(instant),
+ TimeZone.SHORT,
+ (l == null) ? Locale.US : l));
+ break;
+ }
+ sb.append(zid.getId());
+ break;
+ }
+ // Date
+ case DateTime.NAME_OF_DAY_ABBREV: // 'a'
+ case DateTime.NAME_OF_DAY: { // 'A'
+ int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1;
+ Locale lt = ((l == null) ? Locale.US : l);
+ DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
+ if (c == DateTime.NAME_OF_DAY)
+ sb.append(dfs.getWeekdays()[i]);
+ else
+ sb.append(dfs.getShortWeekdays()[i]);
+ break;
+ }
+ case DateTime.NAME_OF_MONTH_ABBREV: // 'b'
+ case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
+ case DateTime.NAME_OF_MONTH: { // 'B'
+ int i = t.get(ChronoField.MONTH_OF_YEAR) - 1;
+ Locale lt = ((l == null) ? Locale.US : l);
+ DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
+ if (c == DateTime.NAME_OF_MONTH)
+ sb.append(dfs.getMonths()[i]);
+ else
+ sb.append(dfs.getShortMonths()[i]);
+ break;
+ }
+ case DateTime.CENTURY: // 'C' (00 - 99)
+ case DateTime.YEAR_2: // 'y' (00 - 99)
+ case DateTime.YEAR_4: { // 'Y' (0000 - 9999)
+ int i = t.get(ChronoField.YEAR_OF_ERA);
+ int size = 2;
+ switch (c) {
+ case DateTime.CENTURY:
+ i /= 100;
+ break;
+ case DateTime.YEAR_2:
+ i %= 100;
+ break;
+ case DateTime.YEAR_4:
+ size = 4;
+ break;
+ }
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, i, flags, size, l));
+ break;
+ }
+ case DateTime.DAY_OF_MONTH_0: // 'd' (01 - 31)
+ case DateTime.DAY_OF_MONTH: { // 'e' (1 - 31) -- like d
+ int i = t.get(ChronoField.DAY_OF_MONTH);
+ Flags flags = (c == DateTime.DAY_OF_MONTH_0
+ ? Flags.ZERO_PAD
+ : Flags.NONE);
+ sb.append(localizedMagnitude(null, i, flags, 2, l));
+ break;
+ }
+ case DateTime.DAY_OF_YEAR: { // 'j' (001 - 366)
+ int i = t.get(ChronoField.DAY_OF_YEAR);
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, i, flags, 3, l));
+ break;
+ }
+ case DateTime.MONTH: { // 'm' (01 - 12)
+ int i = t.get(ChronoField.MONTH_OF_YEAR);
+ Flags flags = Flags.ZERO_PAD;
+ sb.append(localizedMagnitude(null, i, flags, 2, l));
+ break;
+ }
+
+ // Composites
+ case DateTime.TIME: // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS)
+ case DateTime.TIME_24_HOUR: { // 'R' (hh:mm same as %H:%M)
+ char sep = ':';
+ print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep);
+ print(sb, t, DateTime.MINUTE, l);
+ if (c == DateTime.TIME) {
+ sb.append(sep);
+ print(sb, t, DateTime.SECOND, l);
+ }
+ break;
+ }
+ case DateTime.TIME_12_HOUR: { // 'r' (hh:mm:ss [AP]M)
+ char sep = ':';
+ print(sb, t, DateTime.HOUR_0, l).append(sep);
+ print(sb, t, DateTime.MINUTE, l).append(sep);
+ print(sb, t, DateTime.SECOND, l).append(' ');
+ // this may be in wrong place for some locales
+ StringBuilder tsb = new StringBuilder();
+ print(tsb, t, DateTime.AM_PM, l);
+ sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
+ break;
+ }
+ case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999)
+ char sep = ' ';
+ print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep);
+ print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep);
+ print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
+ print(sb, t, DateTime.TIME, l).append(sep);
+ print(sb, t, DateTime.ZONE, l).append(sep);
+ print(sb, t, DateTime.YEAR_4, l);
+ break;
+ }
+ case DateTime.DATE: { // 'D' (mm/dd/yy)
+ char sep = '/';
+ print(sb, t, DateTime.MONTH, l).append(sep);
+ print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep);
+ print(sb, t, DateTime.YEAR_2, l);
+ break;
+ }
+ case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d)
+ char sep = '-';
+ print(sb, t, DateTime.YEAR_4, l).append(sep);
+ print(sb, t, DateTime.MONTH, l).append(sep);
+ print(sb, t, DateTime.DAY_OF_MONTH_0, l);
+ break;
+ }
+ default:
+ assert false;
+ }
+ } catch (DateTimeException x) {
+ throw new IllegalFormatConversionException(c, t.getClass());
+ }
+ return sb;
+ }
+
// -- Methods to support throwing exceptions --
private void failMismatch(Flags f, char c) {
diff --git a/ojluni/src/main/java/sun/net/InetAddressCachePolicy.java b/ojluni/src/main/java/sun/net/InetAddressCachePolicy.java
deleted file mode 100644
index f22e435..0000000
--- a/ojluni/src/main/java/sun/net/InetAddressCachePolicy.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1998, 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.net;
-
-import java.security.PrivilegedAction;
-import java.security.Security;
-
-public final class InetAddressCachePolicy {
-
- // Controls the cache policy for successful lookups only
- private static final String cachePolicyProp = "networkaddress.cache.ttl";
- private static final String cachePolicyPropFallback =
- "sun.net.inetaddr.ttl";
-
- // Controls the cache policy for negative lookups only
- private static final String negativeCachePolicyProp =
- "networkaddress.cache.negative.ttl";
- private static final String negativeCachePolicyPropFallback =
- "sun.net.inetaddr.negative.ttl";
-
- public static final int FOREVER = -1;
- public static final int NEVER = 0;
-
- /* default value for positive lookups */
- // ----- BEGIN android -----
- //public static final int DEFAULT_POSITIVE = 30;
- // The TTL for the android Java-level cache is short, just 2s.
- public static final int DEFAULT_POSITIVE = 2;
- // ----- END android -----
-
- /* The Java-level namelookup cache policy for successful lookups:
- *
- * -1: caching forever
- * any positive value: the number of seconds to cache an address for
- *
- * default value is forever (FOREVER), as we let the platform do the
- * caching. For security reasons, this caching is made forever when
- * a security manager is set.
- */
- private static int cachePolicy = FOREVER;
-
- /* The Java-level namelookup cache policy for negative lookups:
- *
- * -1: caching forever
- * any positive value: the number of seconds to cache an address for
- *
- * default value is 0. It can be set to some other value for
- * performance reasons.
- */
- private static int negativeCachePolicy = NEVER;
-
- /*
- * Whether or not the cache policy for successful lookups was set
- * using a property (cmd line).
- */
- private static boolean propertySet;
-
- /*
- * Whether or not the cache policy for negative lookups was set
- * using a property (cmd line).
- */
- private static boolean propertyNegativeSet;
-
- /*
- * Initialize
- */
- static {
- Integer tmp = null;
-
- try {
- tmp = new Integer(
- java.security.AccessController.doPrivileged (
- new PrivilegedAction<String>() {
- public String run() {
- return Security.getProperty(cachePolicyProp);
- }
- }));
- } catch (NumberFormatException e) {
- // ignore
- }
- if (tmp != null) {
- cachePolicy = tmp.intValue();
- if (cachePolicy < 0) {
- cachePolicy = FOREVER;
- }
- propertySet = true;
- } else {
- tmp = java.security.AccessController.doPrivileged
- (new sun.security.action.GetIntegerAction(cachePolicyPropFallback));
- if (tmp != null) {
- cachePolicy = tmp.intValue();
- if (cachePolicy < 0) {
- cachePolicy = FOREVER;
- }
- propertySet = true;
- } else {
- /* No properties defined for positive caching. If there is no
- * security manager then use the default positive cache value.
- */
- if (System.getSecurityManager() == null) {
- cachePolicy = DEFAULT_POSITIVE;
- }
- }
- }
-
- try {
- tmp = new Integer(
- java.security.AccessController.doPrivileged (
- new PrivilegedAction<String>() {
- public String run() {
- return Security.getProperty(negativeCachePolicyProp);
- }
- }));
- } catch (NumberFormatException e) {
- // ignore
- }
-
- if (tmp != null) {
- negativeCachePolicy = tmp.intValue();
- if (negativeCachePolicy < 0) {
- negativeCachePolicy = FOREVER;
- }
- propertyNegativeSet = true;
- } else {
- tmp = java.security.AccessController.doPrivileged
- (new sun.security.action.GetIntegerAction(negativeCachePolicyPropFallback));
- if (tmp != null) {
- negativeCachePolicy = tmp.intValue();
- if (negativeCachePolicy < 0) {
- negativeCachePolicy = FOREVER;
- }
- propertyNegativeSet = true;
- }
- }
- }
-
- public static synchronized int get() {
- return cachePolicy;
- }
-
- public static synchronized int getNegative() {
- return negativeCachePolicy;
- }
-
- /**
- * Sets the cache policy for successful lookups if the user has not
- * already specified a cache policy for it using a
- * command-property.
- * @param newPolicy the value in seconds for how long the lookup
- * should be cached
- */
- public static synchronized void setIfNotSet(int newPolicy) {
- /*
- * When setting the new value we may want to signal that the
- * cache should be flushed, though this doesn't seem strictly
- * necessary.
- */
- if (!propertySet) {
- checkValue(newPolicy, cachePolicy);
- cachePolicy = newPolicy;
- }
- }
-
- /**
- * Sets the cache policy for negative lookups if the user has not
- * already specified a cache policy for it using a
- * command-property.
- * @param newPolicy the value in seconds for how long the lookup
- * should be cached
- */
- public static synchronized void setNegativeIfNotSet(int newPolicy) {
- /*
- * When setting the new value we may want to signal that the
- * cache should be flushed, though this doesn't seem strictly
- * necessary.
- */
- if (!propertyNegativeSet) {
- // Negative caching does not seem to have any security
- // implications.
- // checkValue(newPolicy, negativeCachePolicy);
- negativeCachePolicy = newPolicy;
- }
- }
-
- private static void checkValue(int newPolicy, int oldPolicy) {
- /*
- * If malicious code gets a hold of this method, prevent
- * setting the cache policy to something laxer or some
- * invalid negative value.
- */
- if (newPolicy == FOREVER)
- return;
-
- if ((oldPolicy == FOREVER) ||
- (newPolicy < oldPolicy) ||
- (newPolicy < FOREVER)) {
-
- throw new
- SecurityException("can't make InetAddress cache more lax");
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/net/RegisteredDomain.java b/ojluni/src/main/java/sun/net/RegisteredDomain.java
deleted file mode 100644
index 49c67c2..0000000
--- a/ojluni/src/main/java/sun/net/RegisteredDomain.java
+++ /dev/null
@@ -1,879 +0,0 @@
-/*
- * Copyright (c) 2011, 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.net;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/*
- * The naming tables listed below were gathered from publicly available data such as
- * the subdomain registration websites listed for each top-level domain by the Internet
- * Assigned Numbers Authority and the website of the Internet Corporation for Assigned Names
- * and Numbers as well as Wikipedia.
- */
-
-public class RegisteredDomain {
-
-// XX.AA
-private static Set<String> top1Set = new HashSet<String>(Arrays.asList("asia", "biz", "cat", "coop",
- "edu", "info", "gov", "jobs", "travel", "am", "aq", "ax", "cc", "cf", "cg", "ch", "cv", "cz",
- "de", "dj", "dk", "fm", "fo", "ga", "gd", "gf", "gl", "gm", "gq", "gs", "gw", "hm",
- "li", "lu", "md", "mh", "mil", "mobi", "mq", "ms", "ms", "ne", "nl", "nu", "si",
- "sm", "sr", "su", "tc", "td", "tf", "tg", "tk", "tm", "tv", "va", "vg",
- /* ae */ "xn--mgbaam7a8h", /* cn s */ "xn--fiqs8s", /* cn t */ "xn--fiqz9s",
- /* eg */ "xn--wgbh1c", /* hk */ "xn--j6w193g", /* jo */ "xn--mgbayh7gpa",
- /* lk */ "xn--fzc2c9e2c", /* ps */ "xn--ygbi2ammx", /* ru */ "xn--p1ai",
- /* qa */ "xn--wgbl6a", /* sa */ "xn--mgberp4a5d4ar", /* sg */ "xn--yfro4i67o",
- /* th */ "xn--o3cw4h", /* tn */ "xn--pgbs0dh", /* tw s */ "xn--kpry57d",
- /* tw */ "xn--kprw13d", /* sg tamil */ "xn--clchc0ea0b2g2a9gcd"));
-
-// common pattern: XX.AA or XX.GOV.AA
-private static Set<String> top2Set = new HashSet<String>(Arrays.asList("as", "bf", "cd", "cx",
- "ie", "lt", "mr", "tl"));
-
-// common pattern: XX.AA or XX.COM.AA or XX.EDU.AA or XX.NET.AA or XX.ORG.AA or XX.GOV.AA
-private static Set<String> top4Set = new HashSet<String>(Arrays.asList("af", "bm", "bs", "bt",
- "bz", "dm", "ky", "lb", "lr", "mo", "sc", "sl", "ws"));
-
-// AA or less than 3 other XX.BB.AA possible matches
-private static Set<String> top3Set = new HashSet<String>(Arrays.asList("ad", "aw", "be", "bw",
- "cl", "fi", "int", "io", "mc"));
-
-// AA.UK exceptions
-private static Set<String> ukSet = new HashSet<String>(Arrays.asList( "bl", "british-library",
- "jet", "nhs", "nls", "parliament", "mod", "police"));
-
-// AA.AR exceptions
-private static Set<String> arSet = new HashSet<String>(Arrays.asList( "argentina", "educ",
- "gobiernoelectronico", "nic", "promocion", "retina", "uba"));
-
-// AA.OM exceptions
-private static Set<String> omSet = new HashSet<String>(Arrays.asList("mediaphone", "nawrastelecom",
- "nawras", "omanmobile", "omanpost", "omantel", "rakpetroleum", "siemens", "songfest",
- "statecouncil", "shura", "peie", "omran", "omnic", "omanet", "oman", "muriya", "kom"));
-
-// any XX.BB.AA
-private static Set<String> top5Set = new HashSet<String>(Arrays.asList("au", "arpa", "bd", "bn", "ck",
- "cy", "er", "et", "fj", "fk", "gt", "gu", "il", "jm", "ke", "kh", "kw",
- "mm", "mt", "mz", "ni", "np", "nz", "pg", "sb", "sv", "tz", "uy", "ve", "ye",
- "za", "zm", "zw"));
-
-// XX.CC.BB.JP
-private static Set<String> jpSet = new HashSet<String>(Arrays.asList("aichi", "akita", "aomori",
- "chiba", "ehime", "fukui", "fukuoka", "fukushima", "gifu", "gunma", "hiroshima", "hokkaido",
- "hyogo", "ibaraki", "ishikawa", "iwate", "kagawa", "kagoshima", "kanagawa", "kawasaki",
- "kitakyushu", "kobe", "kochi", "kumamoto", "kyoto", "mie", "miyagi", "miyazaki", "nagano",
- "nagasaki", "nagoya", "nara", "niigata", "oita", "okayama", "okinawa", "osaka", "saga",
- "saitama", "sapporo", "sendai", "shiga", "shimane", "shizuoka", "tochigi", "tokushima",
- "tokyo", "tottori", "toyama", "wakayama", "yamagata", "yamaguchi", "yamanashi", "yokohama"));
-
-// CC.BB.JP exceptions
-private static Set<String> jp2Set = new HashSet<String>(Arrays.asList("metro.tokyo.jp",
- "pref.aichi.jp", "pref.akita.jp", "pref.aomori.jp", "pref.chiba.jp", "pref.ehime.jp",
- "pref.fukui.jp", "pref.fukuoka.jp", "pref.fukushima.jp", "pref.gifu.jp", "pref.gunma.jp",
- "pref.hiroshima.jp", "pref.hokkaido.jp", "pref.hyogo.jp", "pref.ibaraki.jp", "pref.ishikawa.jp",
- "pref.iwate.jp", "pref.kagawa.jp", "pref.kagoshima.jp", "pref.kanagawa.jp", "pref.kochi.jp",
- "pref.kumamoto.jp", "pref.kyoto.jp", "pref.mie.jp", "pref.miyagi.jp", "pref.miyazaki.jp",
- "pref.nagano.jp", "pref.nagasaki.jp", "pref.nara.jp", "pref.niigata.jp", "pref.oita.jp",
- "pref.okayama.jp", "pref.okinawa.jp", "pref.osaka.jp", "pref.saga.jp", "pref.saitama.jp",
- "pref.shiga.jp", "pref.shimane.jp", "pref.shizuoka.jp", "pref.tochigi.jp", "pref.tokushima.jp",
- "pref.tottori.jp", "pref.toyama.jp", "pref.wakayama.jp", "pref.yamagata.jp", "pref.yamaguchi.jp",
- "pref.yamanashi.jp", "city.chiba.jp", "city.fukuoka.jp", "city.hamamatsu.jp", "city.hiroshima.jp", "city.kawasaki.jp",
- "city.kitakyushu.jp", "city.kobe.jp", "city.kyoto.jp", "city.nagoya.jp", "city.niigata.jp",
- "city.okayama.jp", "city.osaka.jp", "city.sagamihara.jp", "city.saitama.jp", "city.sapporo.jp", "city.sendai.jp",
- "city.shizuoka.jp", "city.yokohama.jp"));
-
-private static Set<String> usStateSet = new HashSet<String>(Arrays.asList("ak",
- "al", "ar", "as", "az", "ca", "co", "ct", "dc", "de", "fl", "ga", "gu", "hi", "ia",
- "id", "il", "in", "ks", "ky", "la", "ma", "md", "me", "mi", "mn", "mo", "ms", "mt",
- "nc", "nd", "ne", "nh", "nj", "nm", "nv", "ny", "oh", "ok", "or", "pa", "pr", "ri",
- "sc", "sd", "tn", "tx", "ut", "vi", "vt", "va", "wa", "wi", "wv", "wy"));
-
-private static Set<String> usSubStateSet = new HashSet<String>(Arrays.asList("state",
- "lib", "k12", "cc", "tec", "gen", "cog", "mus", "dst"));
-
-private static Map<String,Set> topMap = new HashMap<String,Set>();
-private static Map<String,Set> top3Map = new HashMap<String,Set>();
-
-static {
- /*
- * XX.AA or XX.BB.AA
- */
- topMap.put("ac", new HashSet<String>(Arrays.asList("com", "co", "edu", "gov", "net", "mil", "org")));
- topMap.put("ae", new HashSet<String>(Arrays.asList("co", "net", "org", "sch", "ac", "gov", "mil")));
- topMap.put("aero", new HashSet<String>(Arrays.asList("accident-investigation",
- "accident-prevention", "aerobatic", "aeroclub", "aerodrome", "agents", "aircraft",
- "airline", "airport", "air-surveillance", "airtraffic", "air-traffic-control",
- "ambulance", "amusement", "association", "author", "ballooning", "broker", "caa",
- "cargo", "catering", "certification", "championship", "charter", "civilaviation",
- "club", "conference", "consultant", "consulting", "control", "council", "crew",
- "design", "dgca", "educator", "emergency", "engine", "engineer", "entertainment",
- "equipment", "exchange", "express", "federation", "flight", "freight", "fuel",
- "gliding", "government", "groundhandling", "group", "hanggliding", "homebuilt",
- "insurance", "journal", "journalist", "leasing", "logistics", "magazine",
- "maintenance", "marketplace", "media", "microlight", "modelling", "navigation",
- "parachuting", "paragliding", "passenger-association", "pilot", "press", "production",
- "recreation", "repbody", "res", "research", "rotorcraft", "safety", "scientist",
- "services", "show", "skydiving", "software", "student", "taxi", "trader", "trading",
- "trainer", "union", "workinggroup", "works" )));
- topMap.put( "ag", new HashSet<String>(Arrays.asList("com", "org", "net", "co", "nom")));
- topMap.put( "ai", new HashSet<String>(Arrays.asList("off", "com", "net", "org")));
- topMap.put( "al", new HashSet<String>(Arrays.asList("com", "edu", "gov", "mil", "net", "org")));
- topMap.put( "an", new HashSet<String>(Arrays.asList("com")));
- topMap.put( "ao", new HashSet<String>(Arrays.asList("ed", "gv", "og", "co", "pb", "it")));
- topMap.put( "at", new HashSet<String>(Arrays.asList("ac", "co", "gv", "or", "biz", "info", "priv")));
- topMap.put( "az", new HashSet<String>(Arrays.asList("com", "net", "int", "gov", "org", "edu", "info",
- "pp", "mil", "name", "biz")));
- topMap.put( "ba", new HashSet<String>(Arrays.asList("org", "net", "edu", "gov", "mil", "unbi",
- "unmo", "unsa", "untz", "unze", "co", "com", "rs")));
- topMap.put( "bb", new HashSet<String>(Arrays.asList("biz", "com", "edu", "gov", "info", "net", "org",
- "store")));
- topMap.put( "bg", new HashSet<String>(Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
- "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1",
- "2", "3", "4", "5", "6", "7", "8", "9")));
- topMap.put( "bh", new HashSet<String>(Arrays.asList("com", "info", "cc", "edu", "biz", "net",
- "org", "gov")));
- topMap.put( "bi", new HashSet<String>(Arrays.asList("co", "com", "edu", "gov", "info", "or", "org")));
- topMap.put( "bj", new HashSet<String>(Arrays.asList("asso", "barreau", "com", "edu", "gouv", "gov", "mil")));
- topMap.put( "bo", new HashSet<String>(Arrays.asList("com", "edu", "gov", "gob", "int", "org", "net",
- "mil", "tv")));
- topMap.put( "br", new HashSet<String>(Arrays.asList("adm", "adv", "agr", "am", "arq", "art", "ato",
- "b", "bio", "blog", "bmd", "cim", "cng", "cnt", "com", "coop", "ecn", "edu", "emp", "eng",
- "esp", "etc", "eti", "far", "flog", "fm", "fnd", "fot", "fst", "g12", "ggf", "gov",
- "imb", "ind", "inf", "jor", "jus", "lel", "mat", "med", "mil", "mus", "net", "nom",
- "not", "ntr", "odo", "org", "ppg", "pro", "psc", "psi", "qsl", "radio", "rec", "slg",
- "srv", "taxi", "teo", "tmp", "trd", "tur", "tv", "vet", "vlog", "wiki", "zlg")));
- topMap.put( "bw", new HashSet<String>(Arrays.asList("co", "gov", "org")));
- topMap.put( "by", new HashSet<String>(Arrays.asList("gov", "mil", "com", "of")));
- topMap.put( "ca", new HashSet<String>(Arrays.asList("ab", "bc", "mb", "nb", "nf",
- "nl", "ns", "nt", "nu", "on", "pe", "qc", "sk", "yk", "gc")));
- topMap.put( "ci", new HashSet<String>(Arrays.asList("org", "or", "com", "co", "edu",
- "ed", "ac", "net", "go", "asso", "xn--aroport-bya", "int",
- "presse", "md", "gouv")));
- topMap.put( "com", new HashSet<String>(Arrays.asList("ad", "ar", "br", "cn", "de", "eu", "gb",
- "gr", "hu", "jpn", "kr", "no", "qc", "ru", "sa", "se", "uk", "us", "uy", "za")));
- topMap.put( "cm", new HashSet<String>(Arrays.asList("co", "com", "gov", "net")));
- topMap.put( "cn", new HashSet<String>(Arrays.asList("ac", "com", "edu", "gov", "net",
- "org", "mil", "xn--55qx5d", "xn--io0a7i",
- "ah", "bj", "cq", "fj", "gd", "gs", "gz", "gx",
- "ha", "hb", "he", "hi", "hl", "hn", "jl", "js", "jx", "ln", "nm", "nx", "qh",
- "sc", "sd", "sh", "sn", "sx", "tj", "xj", "xz", "yn", "zj", "hk", "mo", "tw")));
- topMap.put( "co", new HashSet<String>(Arrays.asList("arts", "com", "edu", "firm", "gov", "info",
- "int", "mil", "net", "nom", "org", "rec", "web")));
- topMap.put( "cr", new HashSet<String>(Arrays.asList("ac", "co", "ed", "fi", "go", "or", "sa")));
- topMap.put( "cu", new HashSet<String>(Arrays.asList("com", "edu", "org", "net", "gov", "inf")));
- topMap.put( "do", new HashSet<String>(Arrays.asList("com", "edu", "org", "net", "gov", "gob",
- "web", "art", "sld", "mil")));
- topMap.put( "dz", new HashSet<String>(Arrays.asList("com", "org", "net", "gov", "edu", "asso",
- "pol", "art")));
- topMap.put( "ec", new HashSet<String>(Arrays.asList("com", "info", "net", "fin", "k12", "med",
- "pro", "org", "edu", "gov", "gob", "mil")));
- topMap.put( "ee", new HashSet<String>(Arrays.asList("edu", "gov", "riik", "lib", "med", "com",
- "pri", "aip", "org", "fie")));
- topMap.put( "eg", new HashSet<String>(Arrays.asList("com", "edu", "eun", "gov", "mil", "name",
- "net", "org", "sci")));
- topMap.put( "es", new HashSet<String>(Arrays.asList("com", "nom", "org", "gob", "edu")));
- topMap.put( "eu", new HashSet<String>(Arrays.asList("europa")));
- topMap.put( "fr", new HashSet<String>(Arrays.asList("com", "asso", "nom", "prd", "presse",
- "tm", "aeroport", "assedic", "avocat", "avoues", "cci", "chambagri",
- "chirurgiens-dentistes", "experts-comptables", "geometre-expert", "gouv", "greta",
- "huissier-justice", "medecin", "notaires", "pharmacien", "port", "veterinaire")));
- topMap.put( "ge", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "mil", "net", "pvt")));
- topMap.put( "gg", new HashSet<String>(Arrays.asList("co", "org", "net", "sch", "gov")));
- topMap.put( "gh", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "mil")));
- topMap.put( "gi", new HashSet<String>(Arrays.asList("com", "ltd", "gov", "mod", "edu", "org")));
- topMap.put( "gn", new HashSet<String>(Arrays.asList("ac", "com", "edu", "gov", "org", "net")));
- topMap.put( "gp", new HashSet<String>(Arrays.asList("com", "net", "mobi", "edu", "org", "asso")));
- topMap.put( "gr", new HashSet<String>(Arrays.asList("com", "co", "net", "edu", "org", "gov",
- "mil", "mod", "sch")));
- topMap.put( "gy", new HashSet<String>(Arrays.asList("co", "com", "net", "org", "edu", "gov")));
- topMap.put( "hk", new HashSet<String>(Arrays.asList("com", "edu", "gov", "idv", "net", "org",
- /* com */ "xn--55qx5d", /* edu */ "xn--wcvs22d", /* gov */"xn--mxtq1m",
- /* idv */ "xn--gmqw5a", /* net */ "xn--od0alg", /*org*/ "xn--uc0atv")));
- topMap.put( /* hk */ "xn--j6w193g", new HashSet<String>(Arrays.asList(
- /* com */ "xn--55qx5d", /* edu */ "xn--wcvs22d", /* gov */"xn--mxtq1m",
- /* idv */ "xn--gmqw5a", /* net */ "xn--od0alg", /*org*/ "xn--uc0atv")));
- topMap.put( "hn", new HashSet<String>(Arrays.asList("com", "edu", "org", "net", "mil", "gob")));
- topMap.put( "hr", new HashSet<String>(Arrays.asList("iz.hr", "from.hr", "name.hr", "com.hr")));
- topMap.put( "ht", new HashSet<String>(Arrays.asList("com", "shop", "firm", "info", "adult",
- "net", "pro", "org", "med", "art", "coop", "pol", "asso", "edu", "rel", "gouv", "perso")));
- topMap.put( "hu", new HashSet<String>(Arrays.asList("co", "info", "org", "priv", "sport", "tm",
- "2000", "agrar", "bolt", "casino", "city", "erotica", "erotika", "film", "forum",
- "games", "hotel", "ingatlan", "jogasz", "konyvelo", "lakas", "media", "news", "reklam",
- "sex", "shop", "suli", "szex", "tozsde", "utazas", "video")));
- topMap.put( "id", new HashSet<String>(Arrays.asList("ac", "co", "go", "mil", "net", "or", "sch",
- "web")));
- topMap.put( "im", new HashSet<String>(Arrays.asList("co.im", "com", "net.im", "gov.im", "org.im",
- "ac.im")));
- topMap.put( "in", new HashSet<String>(Arrays.asList("co", "firm", "ernet", "net", "org", "gen", "ind",
- "nic", "ac", "edu", "res", "gov", "mil")));
- topMap.put( "iq", new HashSet<String>(Arrays.asList("gov", "edu", "mil", "com", "org", "net" )));
- topMap.put( "ir", new HashSet<String>(Arrays.asList("ac", "co", "gov", "id", "net", "org", "sch"
- )));
- topMap.put( "is", new HashSet<String>(Arrays.asList("net", "com", "edu", "gov", "org", "int")));
- topMap.put( "it", new HashSet<String>(Arrays.asList("gov", "edu", "agrigento", "ag", "alessandria",
- "al", "ancona", "an", "aosta", "aoste", "ao", "arezzo", "ar", "ascoli-piceno",
- "ascolipiceno", "ap", "asti", "at", "avellino", "av", "bari", "ba",
- "andria-barletta-trani", "andriabarlettatrani", "trani-barletta-andria",
- "tranibarlettaandria", "barletta-trani-andria", "barlettatraniandria",
- "andria-trani-barletta", "andriatranibarletta", "trani-andria-barletta",
- "traniandriabarletta", "bt", "belluno", "bl", "benevento", "bn", "bergamo", "bg",
- "biella", "bi", "bologna", "bo", "bolzano", "bozen", "balsan", "alto-adige",
- "altoadige", "suedtirol", "bz", "brescia", "bs", "brindisi", "br", "cagliari",
- "ca", "caltanissetta", "cl", "campobasso", "cb", "carboniaiglesias", "carbonia-iglesias",
- "iglesias-carbonia", "iglesiascarbonia", "ci", "caserta", "ce", "catania", "ct",
- "catanzaro", "cz", "chieti", "ch", "como", "co", "cosenza", "cs", "cremona", "cr",
- "crotone", "kr", "cuneo", "cn", "dell-ogliastra", "dellogliastra", "ogliastra", "og",
- "enna", "en", "ferrara", "fe", "fermo", "fm", "firenze", "florence", "fi", "foggia",
- "fg", "forli-cesena", "forlicesena", "cesena-forli", "cesenaforli", "fc", "frosinone",
- "fr", "genova", "genoa", "ge", "gorizia", "go", "grosseto", "gr", "imperia", "im",
- "isernia", "is", "laquila", "aquila", "aq", "la-spezia", "laspezia", "sp", "latina",
- "lt", "lecce", "le", "lecco", "lc", "livorno", "li", "lodi", "lo", "lucca", "lu",
- "macerata", "mc", "mantova", "mn", "massa-carrara", "massacarrara", "carrara-massa",
- "carraramassa", "ms", "matera", "mt", "medio-campidano", "mediocampidano",
- "campidano-medio", "campidanomedio", "vs", "messina", "me", "milano", "milan",
- "mi", "modena", "mo", "monza", "monza-brianza", "monzabrianza", "monzaebrianza",
- "monzaedellabrianza", "monza-e-della-brianza", "mb", "napoli", "naples", "na",
- "novara", "no", "nuoro", "nu", "oristano", "or", "padova", "padua", "pd", "palermo",
- "pa", "parma", "pr", "pavia", "pv", "perugia", "pg", "pescara", "pe", "pesaro-urbino",
- "pesarourbino", "urbino-pesaro", "urbinopesaro", "pu", "piacenza", "pc", "pisa",
- "pi", "pistoia", "pt", "pordenone", "pn", "potenza", "pz", "prato", "po", "ragusa",
- "rg", "ravenna", "ra", "reggio-calabria", "reggiocalabria", "rc", "reggio-emilia",
- "reggioemilia", "re", "rieti", "ri", "rimini", "rn", "roma", "rome", "rm", "rovigo",
- "ro", "salerno", "sa", "sassari", "ss", "savona", "sv", "siena", "si", "siracusa",
- "sr", "sondrio", "so", "taranto", "ta", "tempio-olbia", "tempioolbia", "olbia-tempio",
- "olbiatempio", "ot", "teramo", "te", "terni", "tr", "torino", "turin", "to",
- "trapani", "tp", "trento", "trentino", "tn", "treviso", "tv", "trieste", "ts",
- "udine", "ud", "varese", "va", "venezia", "venice", "ve", "verbania", "vb",
- "vercelli", "vc", "verona", "vr", "vibo-valentia", "vibovalentia", "vv", "vicenza",
- "vi", "viterbo", "vt")));
- topMap.put( "je", new HashSet<String>(Arrays.asList("co", "org", "net", "sch", "gov")));
- topMap.put( "jo", new HashSet<String>(Arrays.asList("com", "org", "net", "edu", "sch",
- "gov", "mil", "name")));
- topMap.put( "jp", new HashSet<String>(Arrays.asList("ac", "ad", "co", "ed", "go", "gr", "lg",
- "ne", "or")));
- topMap.put( "kg", new HashSet<String>(Arrays.asList("org", "net", "com", "edu", "gov", "mil")));
- topMap.put( "ki", new HashSet<String>(Arrays.asList("edu", "biz", "net", "org", "gov",
- "info", "com")));
- topMap.put( "km", new HashSet<String>(Arrays.asList("org", "nom", "gov", "prd", "tm", "edu",
- "mil", "ass", "com", "coop", "asso", "presse", "medecin", "notaires", "pharmaciens",
- "veterinaire", "gouv")));
- topMap.put( "kn", new HashSet<String>(Arrays.asList("net", "org", "edu", "gov")));
- topMap.put( "kp", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "rep", "tra")));
- topMap.put( "kr", new HashSet<String>(Arrays.asList("ac", "co", "es", "go", "hs", "kg", "mil",
- "ms", "ne", "or", "pe", "re", "sc", "busan", "chungbuk", "chungnam", "daegu",
- "daejeon", "gangwon", "gwangju", "gyeongbuk", "gyeonggi", "gyeongnam", "incheon",
- "jeju", "jeonbuk", "jeonnam", "seoul", "ulsan")));
- topMap.put( "kz", new HashSet<String>(Arrays.asList("org", "edu", "net", "gov", "mil", "com")));
- topMap.put( "la", new HashSet<String>(Arrays.asList("int", "net", "info", "edu", "gov", "per",
- "com", "org", "c")));
- topMap.put( "lc", new HashSet<String>(Arrays.asList("com", "net", "co", "org", "edu", "gov",
- "l.lc", "p.lc")));
- topMap.put( "lk", new HashSet<String>(Arrays.asList("gov", "sch", "net", "int", "com", "org",
- "edu", "ngo", "soc", "web", "ltd", "assn", "grp", "hotel")));
- topMap.put( "ls", new HashSet<String>(Arrays.asList("co", "gov", "ac", "org")));
- topMap.put( "lv", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "mil",
- "id", "net", "asn", "conf")));
- topMap.put( "ly", new HashSet<String>(Arrays.asList("com", "net", "gov", "plc", "edu", "sch",
- "med", "org", "id")));
- topMap.put( "ma", new HashSet<String>(Arrays.asList("co", "net", "gov", "org", "ac", "press")));
- topMap.put( "me", new HashSet<String>(Arrays.asList("co", "net", "org", "edu", "ac", "gov",
- "its", "priv")));
- topMap.put( "mg", new HashSet<String>(Arrays.asList("org", "nom", "gov", "prd", "tm",
- "edu", "mil", "com")));
- topMap.put( "mk", new HashSet<String>(Arrays.asList("com", "org", "net", "edu", "gov", "inf",
- "name", "pro")));
- topMap.put( "ml", new HashSet<String>(Arrays.asList("com", "edu", "gouv", "gov", "net",
- "org", "presse")));
- topMap.put( "mn", new HashSet<String>(Arrays.asList("gov", "edu", "org")));
- topMap.put( "mp", new HashSet<String>(Arrays.asList("gov", "co", "org")));
- topMap.put( "mu", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "ac",
- "co", "or")));
- topMap.put( "museum", new HashSet<String>(Arrays.asList("academy", "agriculture", "air",
- "airguard", "alabama", "alaska", "amber", "ambulance", "american", "americana",
- "americanantiques", "americanart", "amsterdam", "and", "annefrank", "anthro",
- "anthropology", "antiques", "aquarium", "arboretum", "archaeological", "archaeology",
- "architecture", "art", "artanddesign", "artcenter", "artdeco", "arteducation",
- "artgallery", "arts", "artsandcrafts", "asmatart", "assassination", "assisi",
- "association", "astronomy", "atlanta", "austin", "australia", "automotive", "aviation",
- "axis", "badajoz", "baghdad", "bahn", "bale", "baltimore", "barcelona", "baseball",
- "basel", "baths", "bauern", "beauxarts", "beeldengeluid", "bellevue", "bergbau",
- "berkeley", "berlin", "bern", "bible", "bilbao", "bill", "birdart", "birthplace",
- "bonn", "boston", "botanical", "botanicalgarden", "botanicgarden", "botany",
- "brandywinevalley", "brasil", "bristol", "british", "britishcolumbia", "broadcast",
- "brunel", "brussel", "brussels", "bruxelles", "building", "burghof", "bus", "bushey",
- "cadaques", "california", "cambridge", "can", "canada", "capebreton", "carrier",
- "cartoonart", "casadelamoneda", "castle", "castres", "celtic", "center", "chattanooga",
- "cheltenham", "chesapeakebay", "chicago", "children", "childrens", "childrensgarden",
- "chiropractic", "chocolate", "christiansburg", "cincinnati", "cinema", "circus",
- "civilisation", "civilization", "civilwar", "clinton", "clock", "coal", "coastaldefence",
- "cody", "coldwar", "collection", "colonialwilliamsburg", "coloradoplateau", "columbia",
- "columbus", "communication", "communications", "community", "computer",
- "computerhistory", "xn--comunicaes-v6a2o", "contemporary", "contemporaryart",
- "convent", "copenhagen", "corporation", "xn--correios-e-telecomunicaes-ghc29a",
- "corvette", "costume", "countryestate", "county", "crafts", "cranbrook", "creation",
- "cultural", "culturalcenter", "culture", "cyber", "cymru", "dali", "dallas", "database",
- "ddr", "decorativearts", "delaware", "delmenhorst", "denmark", "depot", "design",
- "detroit", "dinosaur", "discovery", "dolls", "donostia", "durham", "eastafrica",
- "eastcoast", "education", "educational", "egyptian", "eisenbahn", "elburg",
- "elvendrell", "embroidery", "encyclopedic", "england", "entomology", "environment",
- "environmentalconservation", "epilepsy", "essex", "estate", "ethnology", "exeter",
- "exhibition", "family", "farm", "farmequipment", "farmers", "farmstead", "field",
- "figueres", "filatelia", "film", "fineart", "finearts", "finland", "flanders", "florida",
- "force", "fortmissoula", "fortworth", "foundation", "francaise", "frankfurt",
- "franziskaner", "freemasonry", "freiburg", "fribourg", "frog", "fundacio", "furniture",
- "gallery", "garden", "gateway", "geelvinck", "gemological", "geology", "georgia",
- "giessen", "glas", "glass", "gorge", "grandrapids", "graz", "guernsey", "halloffame",
- "hamburg", "handson", "harvestcelebration", "hawaii", "health", "heimatunduhren",
- "hellas", "helsinki", "hembygdsforbund", "heritage", "histoire", "historical",
- "historicalsociety", "historichouses", "historisch", "historisches", "history",
- "historyofscience", "horology", "house", "humanities", "illustration", "imageandsound",
- "indian", "indiana", "indianapolis", "indianmarket", "intelligence", "interactive",
- "iraq", "iron", "isleofman", "jamison", "jefferson", "jerusalem", "jewelry",
- "jewish", "jewishart", "jfk", "journalism", "judaica", "judygarland", "juedisches",
- "juif", "karate", "karikatur", "kids", "koebenhavn", "koeln", "kunst", "kunstsammlung",
- "kunstunddesign", "labor", "labour", "lajolla", "lancashire", "landes", "lans",
- "xn--lns-qla", "larsson", "lewismiller", "lincoln", "linz", "living", "livinghistory",
- "localhistory", "london", "losangeles", "louvre", "loyalist", "lucerne", "luxembourg",
- "luzern", "mad", "madrid", "mallorca", "manchester", "mansion", "mansions", "manx",
- "marburg", "maritime", "maritimo", "maryland", "marylhurst", "media", "medical",
- "medizinhistorisches", "meeres", "memorial", "mesaverde", "michigan", "midatlantic",
- "military", "mill", "miners", "mining", "minnesota", "missile", "missoula", "modern",
- "moma", "money", "monmouth", "monticello", "montreal", "moscow", "motorcycle", "muenchen",
- "muenster", "mulhouse", "muncie", "museet", "museumcenter", "museumvereniging", "music",
- "national", "nationalfirearms", "nationalheritage", "nativeamerican", "naturalhistory",
- "naturalhistorymuseum", "naturalsciences", "nature", "naturhistorisches",
- "natuurwetenschappen", "naumburg", "naval", "nebraska", "neues", "newhampshire",
- "newjersey", "newmexico", "newport", "newspaper", "newyork", "niepce", "norfolk",
- "north", "nrw", "nuernberg", "nuremberg", "nyc", "nyny", "oceanographic",
- "oceanographique", "omaha", "online", "ontario", "openair", "oregon", "oregontrail",
- "otago", "oxford", "pacific", "paderborn", "palace", "paleo", "palmsprings", "panama",
- "paris", "pasadena", "pharmacy", "philadelphia", "philadelphiaarea", "philately",
- "phoenix", "photography", "pilots", "pittsburgh", "planetarium", "plantation",
- "plants", "plaza", "portal", "portland", "portlligat", "posts-and-telecommunications",
- "preservation", "presidio", "press", "project", "public", "pubol", "quebec",
- "railroad", "railway", "research", "resistance", "riodejaneiro", "rochester", "rockart",
- "roma", "russia", "saintlouis", "salem", "salvadordali", "salzburg", "sandiego",
- "sanfrancisco", "santabarbara", "santacruz", "santafe", "saskatchewan", "satx",
- "savannahga", "schlesisches", "schoenbrunn", "schokoladen", "school", "schweiz",
- "science", "scienceandhistory", "scienceandindustry", "sciencecenter", "sciencecenters",
- "science-fiction", "sciencehistory", "sciences", "sciencesnaturelles", "scotland",
- "seaport", "settlement", "settlers", "shell", "sherbrooke", "sibenik", "silk", "ski",
- "skole", "society", "sologne", "soundandvision", "southcarolina", "southwest", "space",
- "spy", "square", "stadt", "stalbans", "starnberg", "state", "stateofdelaware",
- "station", "steam", "steiermark", "stjohn", "stockholm", "stpetersburg", "stuttgart",
- "suisse", "surgeonshall", "surrey", "svizzera", "sweden", "sydney", "tank", "tcm",
- "technology", "telekommunikation", "television", "texas", "textile", "theater",
- "time", "timekeeping", "topology", "torino", "touch", "town", "transport", "tree",
- "trolley", "trust", "trustee", "uhren", "ulm", "undersea", "university", "usa",
- "usantiques", "usarts", "uscountryestate", "usculture", "usdecorativearts", "usgarden",
- "ushistory", "ushuaia", "uslivinghistory", "utah", "uvic", "valley", "vantaa",
- "versailles", "viking", "village", "virginia", "virtual", "virtuel", "vlaanderen",
- "volkenkunde", "wales", "wallonie", "war", "washingtondc", "watchandclock",
- "watch-and-clock", "western", "westfalen", "whaling", "wildlife", "williamsburg",
- "windmill", "workshop", "york", "yorkshire", "yosemite", "youth", "zoological",
- "zoology", "xn--9dbhblg6di", "xn--h1aegh")));
- topMap.put( "mv", new HashSet<String>(Arrays.asList("aero", "biz", "com", "coop", "edu", "gov",
- "info", "int", "mil", "museum", "name", "net", "org", "pro")));
- topMap.put( "mw", new HashSet<String>(Arrays.asList("ac", "biz", "co", "com", "coop", "edu",
- "gov", "int", "museum", "net", "org")));
- topMap.put( "mx", new HashSet<String>(Arrays.asList("com", "org", "gob", "edu", "net")));
- topMap.put( "my", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu",
- "mil", "name", "sch")));
- topMap.put( "na", new HashSet<String>(Arrays.asList("co", "com", "org", "edu", "edunet", "net",
- "alt", "biz", "info")));
- topMap.put( "nc", new HashSet<String>(Arrays.asList("asso", "nom")));
- topMap.put( "net", new HashSet<String>(Arrays.asList("gb", "se", "uk", "za")));
- topMap.put( "ng", new HashSet<String>(Arrays.asList("name", "sch", "mil", "mobi", "com",
- "edu", "gov", "net", "org")));
- topMap.put( "nf", new HashSet<String>(Arrays.asList("com", "net", "per", "rec", "web",
- "arts", "firm", "info", "other", "store")));
- topMap.put( "no", new HashSet<String>(Arrays.asList("fhs", "vgs", "fylkesbibl", "folkebibl",
- "museum", "idrett", "priv", "mil", "stat", "dep", "kommune", "herad", "aa",
- "ah", "bu", "fm", "hl", "hm", "jan-mayen", "mr", "nl", "nt", "of", "ol", "oslo",
- "rl", "sf", "st", "svalbard", "tm", "tr", "va", "vf", "akrehamn",
- "xn--krehamn-dxa", "algard", "xn--lgrd-poac", "arna", "brumunddal",
- "bryne", "bronnoysund", "xn--brnnysund-m8ac", "drobak",
- "xn--drbak-wua", "egersund", "fetsund", "floro", "xn--flor-jra",
- "fredrikstad", "hokksund", "honefoss", "xn--hnefoss-q1a",
- "jessheim", "jorpeland", "xn--jrpeland-54a", "kirkenes", "kopervik",
- "krokstadelva", "langevag", "xn--langevg-jxa", "leirvik", "mjondalen",
- "xn--mjndalen-64a", "mo-i-rana", "mosjoen", "xn--mosjen-eya",
- "nesoddtangen", "orkanger", "osoyro", "xn--osyro-wua",
- "raholt", "xn--rholt-mra", "sandnessjoen", "xn--sandnessjen-ogb",
- "skedsmokorset", "slattum", "spjelkavik", "stathelle", "stavern", "stjordalshalsen",
- "xn--stjrdalshalsen-sqb", "tananger", "tranby", "vossevangen", "tranby",
- "vossevangen", "afjord", "xn--fjord-lra", "agdenes", "al",
- "xn--l-1fa", "alesund", "xn--lesund-hua",
- "alstahaug", "alta", "xn--lt-liac", "alaheadju",
- "xn--laheadju-7ya", "alvdal", "amli", "xn--mli-tla",
- "amot", "xn--mot-tla", "andebu", "andoy", "xn--andy-ira",
- "andasuolo", "ardal", "xn--rdal-poa", "aremark", "arendal",
- "xn--s-1fa", "aseral", "xn--seral-lra",
- "asker", "askim", "askvoll", "askoy", "xn--asky-ira",
- "asnes", "xn--snes-poa", "audnedaln", "aukra", "aure", "aurland",
- "aurskog-holand", "xn--aurskog-hland-jnb",
- "austevoll", "austrheim", "averoy", "xn--avery-yua",
- "balestrand", "ballangen", "balat", "xn--blt-elab",
- "balsfjord", "bahccavuotna", "xn--bhccavuotna-k7a",
- "bamble", "bardu", "beardu", "beiarn", "bajddar", "xn--bjddar-pta",
- "baidar", "xn--bidr-5nac", "berg", "bergen", "berlevag", "xn--berlevg-jxa",
- "bearalvahki", "xn--bearalvhki-y4a", "bindal", "birkenes", "bjarkoy",
- "xn--bjarky-fya", "bjerkreim", "bjugn", "bodo", "xn--bod-2na",
- "badaddja", "xn--bdddj-mrabd", "budejju", "bokn",
- "bremanger", "bronnoy", "xn--brnny-wuac", "bygland",
- "bykle", "barum", "xn--brum-voa", "bievat", "xn--bievt-0qa",
- "bomlo", "xn--bmlo-gra", "batsfjord", "xn--btsfjord-9za", "bahcavuotna",
- "xn--bhcavuotna-s4a", "dovre", "drammen", "drangedal", "dyroy",
- "xn--dyry-ira", "donna", "xn--dnna-gra",
- "eid", "eidfjord", "eidsberg", "eidskog", "eidsvoll", "eigersund", "elverum",
- "enebakk", "engerdal", "etne", "etnedal", "evenes", "evenassi",
- "xn--eveni-0qa01ga", "evje-og-hornnes", "farsund", "fauske",
- "fuossko", "fuoisku", "fedje", "fet", "finnoy", "xn--finny-yua",
- "fitjar", "fjaler", "fjell", "flakstad", "flatanger", "flekkefjord", "flesberg",
- "flora", "fla", "xn--fl-zia", "folldal", "forsand", "fosnes", "frei",
- "frogn", "froland", "frosta", "frana", "xn--frna-woa",
- "froya", "xn--frya-hra", "fusa", "fyresdal", "forde",
- "xn--frde-gra", "gamvik", "gangaviika", "xn--ggaviika-8ya47h",
- "gaular", "gausdal", "gildeskal", "xn--gildeskl-g0a",
- "giske", "gjemnes", "gjerdrum", "gjerstad", "gjesdal", "gjovik",
- "xn--gjvik-wua", "gloppen", "gol", "gran", "grane", "granvin",
- "gratangen", "grimstad", "grong", "kraanghke", "xn--kranghke-b0a",
- "grue", "gulen", "hadsel", "halden", "halsa", "hamar", "hamaroy", "habmer",
- "xn--hbmer-xqa", "hapmir", "xn--hpmir-xqa",
- "hammerfest", "hammarfeasta", "xn--hmmrfeasta-s4ac",
- "haram", "hareid", "harstad", "hasvik", "aknoluokta", "xn--koluokta-7ya57h",
- "hattfjelldal", "aarborte", "haugesund", "hemne", "hemnes", "hemsedal",
- "hitra", "hjartdal", "hjelmeland",
- "hobol", "xn--hobl-ira", "hof", "hol", "hole", "holmestrand", "holtalen",
- "xn--holtlen-hxa", "hornindal", "horten", "hurdal", "hurum", "hvaler",
- "hyllestad", "hagebostad", "xn--hgebostad-g3a", "hoyanger",
- "xn--hyanger-q1a", "hoylandet", "xn--hylandet-54a",
- "ha", "xn--h-2fa", "ibestad", "inderoy", "xn--indery-fya",
- "iveland", "jevnaker", "jondal", "jolster", "xn--jlster-bya",
- "karasjok", "karasjohka", "xn--krjohka-hwab49j",
- "karlsoy", "galsa", "xn--gls-elac", "karmoy",
- "xn--karmy-yua", "kautokeino", "guovdageaidnu", "klepp", "klabu",
- "xn--klbu-woa", "kongsberg", "kongsvinger", "kragero", "xn--krager-gya",
- "kristiansand", "kristiansund", "krodsherad", "xn--krdsherad-m8a",
- "kvalsund", "rahkkeravju", "xn--rhkkervju-01af",
- "kvam", "kvinesdal", "kvinnherad", "kviteseid", "kvitsoy", "xn--kvitsy-fya",
- "kvafjord", "xn--kvfjord-nxa", "giehtavuoatna", "kvanangen",
- "xn--kvnangen-k0a", "navuotna", "xn--nvuotna-hwa",
- "kafjord", "xn--kfjord-iua", "gaivuotna", "xn--givuotna-8ya",
- "larvik", "lavangen", "lavagis", "loabat", "xn--loabt-0qa",
- "lebesby", "davvesiida", "leikanger", "leirfjord", "leka", "leksvik", "lenvik",
- "leangaviika", "xn--leagaviika-52b", "lesja", "levanger", "lier", "lierne",
- "lillehammer", "lillesand", "lindesnes", "lindas", "xn--linds-pra",
- "lom", "loppa", "lahppi", "xn--lhppi-xqa", "lund", "lunner", "luroy",
- "xn--lury-ira", "luster", "lyngdal", "lyngen", "ivgu", "lardal", "lerdal",
- "xn--lrdal-sra", "lodingen", "xn--ldingen-q1a", "lorenskog",
- "xn--lrenskog-54a", "loten", "xn--lten-gra", "malvik",
- "masoy", "xn--msy-ula0h", "muosat", "xn--muost-0qa",
- "mandal", "marker", "marnardal", "masfjorden", "meland", "meldal", "melhus",
- "meloy", "xn--mely-ira", "meraker", "xn--merker-kua", "moareke",
- "xn--moreke-jua", "midsund", "midtre-gauldal", "modalen", "modum",
- "molde", "moskenes", "moss", "mosvik", "malselv", "xn--mlselv-iua",
- "malatvuopmi", "xn--mlatvuopmi-s4a", "namdalseid", "aejrie", "namsos",
- "namsskogan", "naamesjevuemie", "xn--nmesjevuemie-tcba",
- "laakesvuemie", "nannestad", "narvik", "narviika", "naustdal", "nedre-eiker",
- "nesna", "nesodden", "nesseby", "unjarga", "xn--unjrga-rta", "nesset",
- "nissedal", "nittedal", "nord-aurdal", "nord-fron", "nord-odal", "norddal",
- "nordkapp", "davvenjarga", "xn--davvenjrga-y4a", "nordre-land",
- "nordreisa", "raisa", "xn--risa-5na", "nore-og-uvdal", "notodden", "naroy",
- "xn--nry-yla5g", "notteroy", "xn--nttery-byae",
- "odda", "oksnes", "xn--ksnes-uua", "oppdal", "oppegard",
- "xn--oppegrd-ixa", "orkdal", "orland", "xn--rland-uua",
- "orskog", "xn--rskog-uua", "orsta", "xn--rsta-fra",
- "os.hedmark", "os.hordaland", "osen", "osteroy", "xn--ostery-fya",
- "ostre-toten", "xn--stre-toten-zcb", "overhalla", "ovre-eiker",
- "xn--vre-eiker-k8a", "oyer", "xn--yer-zna",
- "oygarden", "xn--ygarden-p1a", "oystre-slidre", "xn--ystre-slidre-ujb",
- "porsanger", "porsangu", "xn--porsgu-sta26f", "porsgrunn",
- "radoy", "xn--rady-ira", "rakkestad", "rana", "ruovat", "randaberg",
- "rauma", "rendalen", "rennebu", "rennesoy", "xn--rennesy-v1a",
- "rindal", "ringebu", "ringerike", "ringsaker", "rissa", "risor",
- "xn--risr-ira", "roan", "rollag", "rygge", "ralingen", "xn--rlingen-mxa",
- "rodoy", "xn--rdy-0nab", "romskog", "xn--rmskog-bya",
- "roros", "xn--rros-gra", "rost", "xn--rst-0na",
- "royken", "xn--ryken-vua", "royrvik", "xn--ryrvik-bya",
- "rade", "xn--rde-ula", "salangen", "siellak", "saltdal", "salat",
- "xn--slt-elab", "xn--slat-5na", "samnanger",
- "sandefjord", "sandnes", "sandoy", "xn--sandy-yua", "sarpsborg",
- "sauda", "sauherad", "sel", "selbu", "selje", "seljord", "sigdal", "siljan",
- "sirdal", "skaun", "skedsmo", "ski", "skien", "skiptvet", "skjervoy",
- "xn--skjervy-v1a", "skierva", "xn--skierv-uta",
- "skjak", "xn--skjk-soa", "skodje", "skanland", "xn--sknland-fxa",
- "skanit", "xn--sknit-yqa", "smola", "xn--smla-hra",
- "snillfjord", "snasa", "xn--snsa-roa", "snoasa", "snaase",
- "xn--snase-nra", "sogndal", "sokndal", "sola", "solund", "songdalen",
- "sortland", "spydeberg", "stange", "stavanger", "steigen", "steinkjer",
- "stjordal", "xn--stjrdal-s1a", "stokke", "stor-elvdal", "stord", "stordal",
- "storfjord", "omasvuotna", "strand", "stranda", "stryn", "sula", "suldal",
- "sund", "sunndal", "surnadal", "sveio", "svelvik", "sykkylven", "sogne",
- "xn--sgne-gra", "somna", "xn--smna-gra", "sondre-land",
- "xn--sndre-land-0cb", "sor-aurdal", "xn--sr-aurdal-l8a",
- "sor-fron", "xn--sr-fron-q1a", "sor-odal", "xn--sr-odal-q1a",
- "sor-varanger", "xn--sr-varanger-ggb", "matta-varjjat",
- "xn--mtta-vrjjat-k7af", "sorfold", "xn--srfold-bya",
- "sorreisa", "xn--srreisa-q1a", "sorum", "xn--srum-gra",
- "tana", "deatnu", "time", "tingvoll", "tinn", "tjeldsund", "dielddanuorri",
- "tjome", "xn--tjme-hra", "tokke", "tolga", "torsken", "tranoy",
- "xn--trany-yua", "tromso", "xn--troms-zua", "tromsa", "romsa",
- "trondheim", "troandin", "trysil", "trana", "xn--trna-woa",
- "trogstad", "xn--trgstad-r1a", "tvedestrand", "tydal", "tynset",
- "tysfjord", "divtasvuodna", "divttasvuotna", "tysnes", "tysvar",
- "xn--tysvr-vra", "tonsberg", "xn--tnsberg-q1a",
- "ullensaker", "ullensvang", "ulvik", "utsira", "vadso", "xn--vads-jra",
- "cahcesuolo", "xn--hcesuolo-7ya35b", "vaksdal", "valle", "vang",
- "vanylven", "vardo", "xn--vard-jra", "varggat", "xn--vrggt-xqad",
- "vefsn", "vaapste", "vega", "vegarshei", "xn--vegrshei-c0a", "vennesla",
- "verdal", "verran", "vestby", "vestnes", "vestre-slidre", "vestre-toten",
- "vestvagoy", "xn--vestvgy-ixa6o", "vevelstad", "vik", "vikna",
- "vindafjord", "volda", "voss", "varoy", "xn--vry-yla5g",
- "vagan", "xn--vgan-qoa", "voagat", "vagsoy", "xn--vgsy-qoa0j",
- "vaga", "xn--vg-yiab")));
-
- topMap.put( "nr", new HashSet<String>(Arrays.asList("biz", "info", "gov", "edu", "org",
- "net", "com", "co")));
- topMap.put( "pa", new HashSet<String>(Arrays.asList("ac", "gob", "com", "org",
- "sld", "edu", "net", "ing", "abo", "med", "nom")));
- topMap.put( "pe", new HashSet<String>(Arrays.asList("edu", "gob", "nom", "mil", "org", "com",
- "net", "sld")));
- topMap.put( "pf", new HashSet<String>(Arrays.asList( "com")));
- topMap.put( "ph", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "ngo", "mil")));
- topMap.put( "pk", new HashSet<String>(Arrays.asList("com", "net", "edu", "org", "fam", "biz",
- "web", "gov", "gob", "gok", "gon", "gop", "gos", "gog", "gkp", "info")));
- topMap.put( "pl", new HashSet<String>(Arrays.asList("aid", "agro", "atm", "auto", "biz", "com",
- "edu", "gmina", "gsm", "info", "mail", "miasta", "media", "mil", "net", "nieruchomosci",
- "nom", "org", "pc", "powiat", "priv", "realestate", "rel", "sex", "shop", "sklep",
- "sos", "szkola", "targi", "tm", "tourism", "travel", "turystyka", "art",
- "gov", "ngo", "augustow", "babia-gora", "bedzin", "beskidy",
- "bialowieza", "bialystok", "bielawa", "bieszczady", "boleslawiec", "bydgoszcz",
- "bytom", "cieszyn", "czeladz", "czest", "dlugoleka", "elblag", "elk", "glogow",
- "gniezno", "gorlice", "grajewo", "ilawa", "jaworzno", "jelenia-gora", "jgora",
- "kalisz", "kazimierz-dolny", "karpacz", "kartuzy", "kaszuby", "katowice", "kepno",
- "ketrzyn", "klodzko", "kobierzyce", "kolobrzeg", "konin", "konskowola", "kutno",
- "lapy", "lebork", "legnica", "lezajsk", "limanowa", "lomza", "lowicz", "lubin",
- "lukow", "malbork", "malopolska", "mazowsze", "mazury", "mielec", "mielno", "mragowo",
- "naklo", "nowaruda", "nysa", "olawa", "olecko", "olkusz", "olsztyn", "opoczno",
- "opole", "ostroda", "ostroleka", "ostrowiec", "ostrowwlkp", "pila", "pisz", "podhale",
- "podlasie", "polkowice", "pomorze", "pomorskie", "prochowice", "pruszkow", "przeworsk",
- "pulawy", "radom", "rawa-maz", "rybnik", "rzeszow", "sanok", "sejny", "siedlce",
- "slask", "slupsk", "sosnowiec", "stalowa-wola", "skoczow", "starachowice", "stargard",
- "suwalki", "swidnica", "swiebodzin", "swinoujscie", "szczecin", "szczytno", "tarnobrzeg",
- "tgory", "turek", "tychy", "ustka", "walbrzych", "warmia", "warszawa", "waw",
- "wegrow", "wielun", "wlocl", "wloclawek", "wodzislaw", "wolomin", "wroclaw",
- "zachpomor", "zagan", "zarow", "zgora", "zgorzelec", "gda", "gdansk",
- "krakow", "poznan", "wroc", "co",
- "lodz", "lublin", "torun")));
- topMap.put( "pn", new HashSet<String>(Arrays.asList("gov", "co", "org", "edu", "net")));
- topMap.put( "pr", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "isla",
- "pro", "biz", "info", "name", "est", "prof", "ac", "gobierno")));
- topMap.put( "pro", new HashSet<String>(Arrays.asList("aca", "bar", "cpa", "jur", "law",
- "med", "eng")));
- topMap.put( "ps", new HashSet<String>(Arrays.asList("edu", "gov", "sec", "plo", "com", "org", "net")));
- topMap.put( "pt", new HashSet<String>(Arrays.asList("net", "gov", "org", "edu", "int", "publ",
- "com", "nome")));
- topMap.put( "pw", new HashSet<String>(Arrays.asList("co", "ne", "or", "ed", "go", "belau")));
- topMap.put( "qa", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "mil")));
- topMap.put( "re", new HashSet<String>(Arrays.asList("com", "asso", "nom")));
- topMap.put( "ro", new HashSet<String>(Arrays.asList("com", "org", "tm", "nt", "nom", "info",
- "rec", "arts", "firm", "store", "www")));
- topMap.put( "rs", new HashSet<String>(Arrays.asList("co", "org", "edu", "ac", "gov", "in")));
- topMap.put( "ru", new HashSet<String>(Arrays.asList("ac", "com", "edu", "int", "net", "org",
- "pp", "adygeya", "altai", "amur", "arkhangelsk", "astrakhan", "bashkiria",
- "belgorod", "bir", "bryansk", "buryatia", "cap", "cbg", "chel", "chelyabinsk", "chita",
- "chukotka", "dagestan", "e-burg", "grozny", "irkutsk",
- "ivanovo", "izhevsk", "jar", "joshkar-ola", "kalmykia", "kaluga", "kamchatka",
- "karelia", "kazan", "kchr", "kemerovo", "khabarovsk", "khakassia", "khv", "kirov",
- "koenig", "komi", "kostroma", "krasnoyarsk", "kuban", "kurgan", "kursk", "lipetsk",
- "magadan", "mari", "mari-el", "marine", "mordovia", "mosreg", "msk", "murmansk",
- "nalchik", "nnov", "nov", "novosibirsk", "nsk", "omsk", "orenburg", "oryol",
- "palana", "penza", "perm", "pskov", "ptz", "rnd", "ryazan", "sakhalin", "samara",
- "saratov", "simbirsk", "smolensk", "spb", "stavropol", "stv", "surgut", "tambov",
- "tatarstan", "tom", "tomsk", "tsaritsyn", "tsk", "tula", "tuva", "tver", "tyumen",
- "udm", "udmurtia", "ulan-ude", "vladikavkaz", "vladimir", "vladivostok", "volgograd",
- "vologda", "voronezh", "vrn", "vyatka", "yakutia", "yamal", "yaroslavl",
- "yekaterinburg", "yuzhno-sakhalinsk", "amursk", "baikal", "cmw", "fareast",
- "jamal", "kms", "k-uralsk", "kustanai", "kuzbass", "magnitka", "mytis",
- "nakhodka", "nkz", "norilsk", "oskol", "pyatigorsk", "rubtsovsk", "snz", "syzran",
- "vdonsk", "zgrad", "gov", "mil", "test")));
- topMap.put( "rw", new HashSet<String>(Arrays.asList("gov", "net", "edu", "ac", "com", "co",
- "int", "mil", "gouv")));
- topMap.put( "sa", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "med", "pub",
- "edu", "sch")));
- topMap.put( "sd", new HashSet<String>(Arrays.asList("com", "net", "org", "edu", "med", "gov",
- "info", "tv")));
- topMap.put( "se", new HashSet<String>(Arrays.asList("a", "ac", "b", "bd", "brand", "c", "d",
- "e", "f", "fh", "fhsk", "fhv", "g", "h", "i", "k", "komforb", "kommunalforbund",
- "komvux", "l", "lanarb", "lanbib", "m", "n", "naturbruksgymn", "o", "org", "p", "parti",
- "pp", "press", "r", "s", "sshn", "t", "tm", "u", "w", "x", "y", "z")));
- topMap.put( "sg", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "per")));
- topMap.put( "sh", new HashSet<String>(Arrays.asList("co", "com", "net", "org", "gov", "edu", "nom")));
- topMap.put( "sk", new HashSet<String>(Arrays.asList("gov", "edu")));
- topMap.put( "sn", new HashSet<String>(Arrays.asList("art", "com", "edu", "gouv", "org", "perso",
- "univ")));
- topMap.put( "so", new HashSet<String>(Arrays.asList("com", "net", "org")));
- topMap.put( "sr", new HashSet<String>(Arrays.asList("co", "com", "consulado", "edu", "embaixada",
- "gov", "mil", "net", "org", "principe", "saotome", "store")));
- topMap.put( "sy", new HashSet<String>(Arrays.asList("edu", "gov", "net", "mil", "com", "org", "news")));
- topMap.put( "sz", new HashSet<String>(Arrays.asList("co", "ac", "org")));
- topMap.put( "th", new HashSet<String>(Arrays.asList("ac", "co", "go", "in", "mi", "net", "or")));
- topMap.put( "tj", new HashSet<String>(Arrays.asList("ac", "biz", "co", "com", "edu", "go", "gov",
- "int", "mil", "name", "net", "nic", "org", "test", "web")));
- topMap.put( "tn", new HashSet<String>(Arrays.asList("com", "ens", "fin", "gov", "ind", "intl",
- "nat", "net", "org", "info", "perso", "tourism", "edunet", "rnrt", "rns", "rnu",
- "mincom", "agrinet", "defense", "turen")));
- topMap.put( "to", new HashSet<String>(Arrays.asList("gov")));
- topMap.put( "tt", new HashSet<String>(Arrays.asList("co", "com", "org", "net", "biz", "info",
- "pro", "int", "coop", "jobs", "mobi", "travel", "museum", "aero", "name", "gov",
- "edu", "cat", "tel", "mil")));
- topMap.put( "tw", new HashSet<String>(Arrays.asList("edu", "gov", "mil", "com", "net", "org",
- "idv", "game", "ebiz", "club", "xn--zf0ao64a", "xn--uc0atv", "xn--czrw28b")));
- topMap.put( "ua", new HashSet<String>(Arrays.asList("com", "edu", "gov", "in", "net", "org",
- "cherkassy", "chernigov", "chernovtsy", "ck", "cn", "crimea", "cv", "dn",
- "dnepropetrovsk", "donetsk", "dp", "if", "ivano-frankivsk", "kh", "kharkov",
- "kherson", "kiev", "kirovograd", "km", "kr", "ks", "lg",
- "lugansk", "lutsk", "lviv", "mk", "nikolaev", "od", "odessa", "pl", "poltava",
- "rovno", "rv", "sebastopol", "sumy", "te", "ternopil", "uzhgorod", "vinnica", "vn",
- "zaporizhzhe", "zp", "zhitomir", "zt", "cr", "lt", "lv", "sb", "sm", "tr",
- "co", "biz", "in", "ne", "pp", "uz", "dominic")));
- topMap.put( "ug", new HashSet<String>(Arrays.asList("co", "ac", "sc", "go", "ne", "or", "org", "com")));
- topMap.put( "us", new HashSet<String>(Arrays.asList("dni", "fed", "isa", "kids", "nsn", "kyschools")));
- topMap.put( "uz", new HashSet<String>(Arrays.asList("co", "com", "org", "gov", "ac", "edu", "int", "pp", "net")));
- topMap.put( "vc", new HashSet<String>(Arrays.asList("com", "net", "org", "gov")));
- topMap.put( "vi", new HashSet<String>(Arrays.asList("co", "com", "k12", "net", "org")));
- topMap.put( "vn", new HashSet<String>(Arrays.asList( "com", "net", "org", "edu", "gov", "int",
- "ac", "biz", "info", "name", "pro", "health")));
- topMap.put( "vu", new HashSet<String>(Arrays.asList("co", "com", "net", "org", "edu", "gov", "de")));
- topMap.put("org", new HashSet<String>(Arrays.asList("ae", "za")));
- topMap.put("pro", new HashSet<String>(Arrays.asList("aca", "bar", "cpa", "jur", "law", "med", "eng")));
-
- top3Map.put("au", new HashSet<String>(Arrays.asList("act.edu.au", "eq.edu.au",
- "nsw.edu.au", "nt.edu.au", "qld.edu.au", "sa.edu.au", "tas.edu.au", "vic.edu.au",
- "wa.edu.au", "act.gov.au", "nsw.gov.au", "nt.gov.au", "qld.gov.au", "sa.gov.au",
- "tas.gov.au", "vic.gov.au", "wa.gov.au")));
- top3Map.put("im", new HashSet<String>(Arrays.asList("ltd.co.im", "plc.co.im")));
- top3Map.put("no", new HashSet<String>(Arrays.asList("gs.aa.no", "gs.ah.no", "gs.bu.no",
- "gs.fm.no", "gs.hl.no", "gs.hm.no", "gs.jan-mayen.no", "gs.mr.no", "gs.nl.no",
- "gs.nt.no", "gs.of.no", "gs.ol.no", "gs.oslo.no", "gs.rl.no", "gs.sf.no",
- "gs.st.no", "gs.svalbard.no", "gs.tm.no", "gs.tr.no", "gs.va.no", "gs.vf.no",
- "bo.telemark.no", "xn--b-5ga.telemark.no", "bo.nordland.no",
- "xn--b-5ga.nordland.no", "heroy.more-og-romsdal.no",
- "xn--hery-ira.xn--mre-og-romsdal-qqb.no", "heroy.nordland.no",
- "xn--hery-ira.nordland.no", "nes.akershus.no", "nes.buskerud.no",
- "os.hedmark.no", "os.hordaland.no",
- "sande.more-og-romsdal.no", "sande.xn--mre-og-romsdal-qqb.no",
- "sande.vestfold.no", "valer.ostfold.no", "xn--vler-qoa.xn--stfold-9xa.no",
- "valer.hedmark.no", "xn--vler-qoa.hedmark.no")));
- top3Map.put("tr", new HashSet<String>(Arrays.asList("gov.nc.tr")));
-}
-
-
- /*
- * Return the registered part of a qualified domain
- * name or the original if no match is found.
- */
- public static String getRegisteredDomain(String cname) {
- int dot;
-
- /*
- * If one dot or less than just return.
- */
- dot = cname.lastIndexOf('.');
- if (dot == -1)
- return cname;
- if (dot == 0)
- return "";
- if (dot == cname.length() - 1) {
- cname = cname.substring(0, cname.length() -1);
- dot = cname.lastIndexOf('.');
- if (dot == -1)
- return cname;
- if (dot == 0)
- return "";
- }
- if (dot == cname.length() - 1)
- return "";
-
- /*
- * Break it up into seperate labels.
- */
- int second = cname.lastIndexOf('.', dot - 1);
- if (second == -1)
- return cname;
- if (second == 0)
- return "";
- int third = cname.lastIndexOf('.', second - 1);
- int fourth = -1;
- if (third > 0) {
- fourth = cname.lastIndexOf('.', third - 1);
- }
- int fifth = -1;
- if (fourth > 0) {
- fifth = cname.lastIndexOf('.', fourth - 1);
- }
- String s = cname.substring(dot + 1);
- String s2 = cname.substring(second + 1, dot);
-
- /*
- * Look for longest matches first.
- * XX.PVT.K12.MA.US etc.
- */
- if (fourth != -1 && s.equals("us") && usStateSet.contains(s2)) {
- String s3 = cname.substring(third + 1, second);
- String s4 = cname.substring(fourth + 1, third);
- if (s3.equals("k12")) {
- if (s2.equals("ma") && (s4.equals("chtr") || s4.equals("paroch"))) {
- return cname.substring(fifth + 1);
- } else if (s4.equals("pvt")) {
- return cname.substring(fifth + 1);
- }
- }
- }
-
- /*
- * XX.K12.MA.US.
- */
- String str = cname.substring(third + 1);
- if (third != -1) {
- Set set = top3Map.get(s);
- if (set != null) {
- if (set.contains(str)) {
- return cname.substring(fourth + 1);
- }
- } else if (s.equals("us") && usStateSet.contains(s2)) {
- // check for known third level labels
- String s3 = cname.substring(third + 1, second);
- if (usSubStateSet.contains(s3)) {
- return fourth != -1? cname.substring(fourth + 1): cname;
- } else {
- return cname.substring(third + 1);
- }
- } else if (s.equals("uk")) {
- if (s2.equals("sch")) {
- return cname.substring(fourth + 1);
- }
- } else if (s.equals("jp")) {
- if (jpSet.contains(s2)) {
- if (jp2Set.contains(str)) {
- return cname.substring(third + 1);
- }
- return cname.substring(fourth + 1);
- }
- }
- }
-
- /*
- * PREF.AKITA.JP etc.
- */
- if (jp2Set.contains(str)) {
- return cname.substring(third + 1);
- }
-
- /*
- * XX.MA.US.
- */
- Set topSet = topMap.get(s);
- if (topSet != null) {
- if (topSet.contains(s2)) {
- return cname.substring(third + 1);
- }
- if (!((s.equals("us") && usStateSet.contains(s2)) || (s.equals("jp") && jpSet.contains(s2)))) {
- return cname.substring(second + 1);
- }
- } else if (top2Set.contains(s)) {
- if (s2.equals("gov")) {
- return cname.substring(third + 1);
- }
- return cname.substring(second + 1);
- } else if (top3Set.contains(s)) {
- if (s.equals("ad") && s2.equals("nom") ||
- s.equals("aw") && s2.equals("com") ||
- s.equals("be") && s2.equals("ac") ||
- s.equals("cl") && s2.equals("gov") ||
- s.equals("cl") && s2.equals("gob") ||
- s.equals("fi") && s2.equals("aland") ||
- s.equals("int") && s2.equals("eu") ||
- s.equals("io") && s2.equals("com") ||
- s.equals("mc") && s2.equals("tm") ||
- s.equals("mc") && s2.equals("asso") ||
- s.equals("vc") && s2.equals("com")) {
- return cname.substring(third + 1);
- }
- return cname.substring(second + 1);
- } else if (top4Set.contains(s)) {
- if (s2.equals("com") || s2.equals("edu") || s2.equals("gov") ||
- s2.equals("net") || s2.equals("org")) {
- return cname.substring(third + 1);
- }
- return cname.substring(second + 1);
- } else if (top5Set.contains(s)) {
- return cname.substring(third + 1);
- }
-
- /*
- * BB.AA exception cases.
- */
- if (s.equals("tr")) {
- if (!s2.equals("nic") && !s2.equals("tsk")) {
- return cname.substring(third + 1);
- }
- return cname.substring(second + 1);
- } else if (s.equals("uk")) {
- if (!ukSet.contains(s2)) {
- return cname.substring(third + 1);
- }
- return cname.substring(second + 1);
- } else if (s.equals("ar")) {
- if (!arSet.contains(s2)) {
- return cname.substring(third + 1);
- }
- return cname.substring(second + 1);
- } else if (s.equals("om")) {
- if (!omSet.contains(s2)) {
- return cname.substring(third + 1);
- }
- return cname.substring(second + 1);
- }
-
- /*
- * XX.AA
- */
- if (top1Set.contains(s)) {
- return cname.substring(second + 1);
- }
-
- /*
- * Nothing matched so we can't shorten the string.
- */
- return cname;
- }
-}
diff --git a/ojluni/src/main/java/sun/net/TransferProtocolClient.java b/ojluni/src/main/java/sun/net/TransferProtocolClient.java
deleted file mode 100644
index 2b74b62..0000000
--- a/ojluni/src/main/java/sun/net/TransferProtocolClient.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 1994, 2002, 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.net;
-
-import java.lang.StringIndexOutOfBoundsException;
-import java.io.*;
-import java.util.Vector;
-import sun.net.NetworkClient;
-
-/**
- * This class implements that basic intefaces of transfer protocols.
- * It is used by subclasses implementing specific protocols.
- *
- * @author Jonathan Payne
- * @see sun.net.ftp.FtpClient
- * @see sun.net.nntp.NntpClient
- */
-
-public class TransferProtocolClient extends NetworkClient {
- static final boolean debug = false;
-
- /** Array of strings (usually 1 entry) for the last reply
- from the server. */
- protected Vector serverResponse = new Vector(1);
-
- /** code for last reply */
- protected int lastReplyCode;
-
-
- /**
- * Pulls the response from the server and returns the code as a
- * number. Returns -1 on failure.
- */
- public int readServerResponse() throws IOException {
- StringBuffer replyBuf = new StringBuffer(32);
- int c;
- int continuingCode = -1;
- int code;
- String response;
-
- serverResponse.setSize(0);
- while (true) {
- while ((c = serverInput.read()) != -1) {
- if (c == '\r') {
- if ((c = serverInput.read()) != '\n')
- replyBuf.append('\r');
- }
- replyBuf.append((char)c);
- if (c == '\n')
- break;
- }
- response = replyBuf.toString();
- replyBuf.setLength(0);
- if (debug) {
- System.out.print(response);
- }
-
- if (response.length() == 0) {
- code = -1;
- } else {
- try {
- code = Integer.parseInt(response.substring(0, 3));
- } catch (NumberFormatException e) {
- code = -1;
- } catch (StringIndexOutOfBoundsException e) {
- /* this line doesn't contain a response code, so
- we just completely ignore it */
- continue;
- }
- }
- serverResponse.addElement(response);
- if (continuingCode != -1) {
- /* we've seen a XXX- sequence */
- if (code != continuingCode ||
- (response.length() >= 4 && response.charAt(3) == '-')) {
- continue;
- } else {
- /* seen the end of code sequence */
- continuingCode = -1;
- break;
- }
- } else if (response.length() >= 4 && response.charAt(3) == '-') {
- continuingCode = code;
- continue;
- } else {
- break;
- }
- }
-
- return lastReplyCode = code;
- }
-
- /** Sends command <i>cmd</i> to the server. */
- public void sendServer(String cmd) {
- serverOutput.print(cmd);
- if (debug) {
- System.out.print("Sending: " + cmd);
- }
- }
-
- /** converts the server response into a string. */
- public String getResponseString() {
- return (String) serverResponse.elementAt(0);
- }
-
- /** Returns all server response strings. */
- public Vector getResponseStrings() {
- return serverResponse;
- }
-
- /** standard constructor to host <i>host</i>, port <i>port</i>. */
- public TransferProtocolClient(String host, int port) throws IOException {
- super(host, port);
- }
-
- /** creates an uninitialized instance of this class. */
- public TransferProtocolClient() {}
-}
diff --git a/ojluni/src/main/java/sun/net/smtp/SmtpClient.java b/ojluni/src/main/java/sun/net/smtp/SmtpClient.java
deleted file mode 100644
index d97b16a..0000000
--- a/ojluni/src/main/java/sun/net/smtp/SmtpClient.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 1995, 2003, 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.net.smtp;
-
-import java.util.StringTokenizer;
-import java.io.*;
-import java.net.*;
-import sun.net.TransferProtocolClient;
-
-/**
- * This class implements the SMTP client.
- * You can send a piece of mail by creating a new SmtpClient, calling
- * the "to" method to add destinations, calling "from" to name the
- * sender, calling startMessage to return a stream to which you write
- * the message (with RFC733 headers) and then you finally close the Smtp
- * Client.
- *
- * @author James Gosling
- */
-
-public class SmtpClient extends TransferProtocolClient {
-
- String mailhost;
- SmtpPrintStream message;
-
- /**
- * issue the QUIT command to the SMTP server and close the connection.
- */
- public void closeServer() throws IOException {
- if (serverIsOpen()) {
- closeMessage();
- issueCommand("QUIT\r\n", 221);
- super.closeServer();
- }
- }
-
- void issueCommand(String cmd, int expect) throws IOException {
- sendServer(cmd);
- int reply;
- while ((reply = readServerResponse()) != expect)
- if (reply != 220) {
- throw new SmtpProtocolException(getResponseString());
- }
- }
-
- private void toCanonical(String s) throws IOException {
- if (s.startsWith("<"))
- issueCommand("rcpt to: " + s + "\r\n", 250);
- else
- issueCommand("rcpt to: <" + s + ">\r\n", 250);
- }
-
- public void to(String s) throws IOException {
- int st = 0;
- int limit = s.length();
- int pos = 0;
- int lastnonsp = 0;
- int parendepth = 0;
- boolean ignore = false;
- while (pos < limit) {
- int c = s.charAt(pos);
- if (parendepth > 0) {
- if (c == '(')
- parendepth++;
- else if (c == ')')
- parendepth--;
- if (parendepth == 0)
- if (lastnonsp > st)
- ignore = true;
- else
- st = pos + 1;
- } else if (c == '(')
- parendepth++;
- else if (c == '<')
- st = lastnonsp = pos + 1;
- else if (c == '>')
- ignore = true;
- else if (c == ',') {
- if (lastnonsp > st)
- toCanonical(s.substring(st, lastnonsp));
- st = pos + 1;
- ignore = false;
- } else {
- if (c > ' ' && !ignore)
- lastnonsp = pos + 1;
- else if (st == pos)
- st++;
- }
- pos++;
- }
- if (lastnonsp > st)
- toCanonical(s.substring(st, lastnonsp));
- }
-
- public void from(String s) throws IOException {
- if (s.startsWith("<"))
- issueCommand("mail from: " + s + "\r\n", 250);
- else
- issueCommand("mail from: <" + s + ">\r\n", 250);
- }
-
- /** open a SMTP connection to host <i>host</i>. */
- private void openServer(String host) throws IOException {
- mailhost = host;
- openServer(mailhost, 25);
- issueCommand("helo "+InetAddress.getLocalHost().getHostName()+"\r\n", 250);
- }
-
- public PrintStream startMessage() throws IOException {
- issueCommand("data\r\n", 354);
- try {
- message = new SmtpPrintStream(serverOutput, this);
- } catch (UnsupportedEncodingException e) {
- throw new InternalError(encoding+" encoding not found");
- }
- return message;
- }
-
- void closeMessage() throws IOException {
- if (message != null)
- message.close();
- }
-
- /** New SMTP client connected to host <i>host</i>. */
- public SmtpClient (String host) throws IOException {
- super();
- if (host != null) {
- try {
- openServer(host);
- mailhost = host;
- return;
- } catch(Exception e) {
- }
- }
- try {
- String s;
- mailhost = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("mail.host"));
- if (mailhost != null) {
- openServer(mailhost);
- return;
- }
- } catch(Exception e) {
- }
- try {
- mailhost = "localhost";
- openServer(mailhost);
- } catch(Exception e) {
- mailhost = "mailhost";
- openServer(mailhost);
- }
- }
-
- /** Create an uninitialized SMTP client. */
- public SmtpClient () throws IOException {
- this(null);
- }
-
- public SmtpClient(int to) throws IOException {
- super();
- setConnectTimeout(to);
- try {
- String s;
- mailhost = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("mail.host"));
- if (mailhost != null) {
- openServer(mailhost);
- return;
- }
- } catch(Exception e) {
- }
- try {
- mailhost = "localhost";
- openServer(mailhost);
- } catch(Exception e) {
- mailhost = "mailhost";
- openServer(mailhost);
- }
- }
-
- public String getMailHost() {
- return mailhost;
- }
-
- String getEncoding () {
- return encoding;
- }
-}
-
-class SmtpPrintStream extends java.io.PrintStream {
- private SmtpClient target;
- private int lastc = '\n';
-
- SmtpPrintStream (OutputStream fos, SmtpClient cl) throws UnsupportedEncodingException {
- super(fos, false, cl.getEncoding());
- target = cl;
- }
-
- public void close() {
- if (target == null)
- return;
- if (lastc != '\n') {
- write('\n');
- }
- try {
- target.issueCommand(".\r\n", 250);
- target.message = null;
- out = null;
- target = null;
- } catch (IOException e) {
- }
- }
-
- public void write(int b) {
- try {
- // quote a dot at the beginning of a line
- if (lastc == '\n' && b == '.') {
- out.write('.');
- }
-
- // translate NL to CRLF
- if (b == '\n' && lastc != '\r') {
- out.write('\r');
- }
- out.write(b);
- lastc = b;
- } catch (IOException e) {
- }
- }
-
- public void write(byte b[], int off, int len) {
- try {
- int lc = lastc;
- while (--len >= 0) {
- int c = b[off++];
-
- // quote a dot at the beginning of a line
- if (lc == '\n' && c == '.')
- out.write('.');
-
- // translate NL to CRLF
- if (c == '\n' && lc != '\r') {
- out.write('\r');
- }
- out.write(c);
- lc = c;
- }
- lastc = lc;
- } catch (IOException e) {
- }
- }
- public void print(String s) {
- int len = s.length();
- for (int i = 0; i < len; i++) {
- write(s.charAt(i));
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/net/smtp/SmtpProtocolException.java b/ojluni/src/main/java/sun/net/smtp/SmtpProtocolException.java
deleted file mode 100644
index d744ebb..0000000
--- a/ojluni/src/main/java/sun/net/smtp/SmtpProtocolException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1995, 2008, 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.net.smtp;
-
-import java.io.IOException;
-
-/**
- * This exeception is thrown when unexpected results are returned during
- * an SMTP session.
- */
-public class SmtpProtocolException extends IOException {
- private static final long serialVersionUID = -7547136771133814908L;
-
- SmtpProtocolException(String s) {
- super(s);
- }
-}
diff --git a/ojluni/src/main/java/sun/net/www/HeaderParser.java b/ojluni/src/main/java/sun/net/www/HeaderParser.java
deleted file mode 100644
index a16b267..0000000
--- a/ojluni/src/main/java/sun/net/www/HeaderParser.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (c) 1996, 2002, 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.net.www;
-
-import java.util.Iterator;
-
-/* This is useful for the nightmare of parsing multi-part HTTP/RFC822 headers
- * sensibly:
- * From a String like: 'timeout=15, max=5'
- * create an array of Strings:
- * { {"timeout", "15"},
- * {"max", "5"}
- * }
- * From one like: 'Basic Realm="FuzzFace" Foo="Biz Bar Baz"'
- * create one like (no quotes in literal):
- * { {"basic", null},
- * {"realm", "FuzzFace"}
- * {"foo", "Biz Bar Baz"}
- * }
- * keys are converted to lower case, vals are left as is....
- *
- * @author Dave Brown
- */
-
-
-public class HeaderParser {
-
- /* table of key/val pairs */
- String raw;
- String[][] tab;
- int nkeys;
- int asize = 10; // initial size of array is 10
-
- public HeaderParser(String raw) {
- this.raw = raw;
- tab = new String[asize][2];
- parse();
- }
-
- private HeaderParser () {
- }
-
- /**
- * create a new HeaderParser from this, whose keys (and corresponding values)
- * range from "start" to "end-1"
- */
- public HeaderParser subsequence (int start, int end) {
- if (start == 0 && end == nkeys) {
- return this;
- }
- if (start < 0 || start >= end || end > nkeys)
- throw new IllegalArgumentException ("invalid start or end");
- HeaderParser n = new HeaderParser ();
- n.tab = new String [asize][2];
- n.asize = asize;
- System.arraycopy (tab, start, n.tab, 0, (end-start));
- n.nkeys= (end-start);
- return n;
- }
-
- private void parse() {
-
- if (raw != null) {
- raw = raw.trim();
- char[] ca = raw.toCharArray();
- int beg = 0, end = 0, i = 0;
- boolean inKey = true;
- boolean inQuote = false;
- int len = ca.length;
- while (end < len) {
- char c = ca[end];
- if ((c == '=') && !inQuote) { // end of a key
- tab[i][0] = new String(ca, beg, end-beg).toLowerCase();
- inKey = false;
- end++;
- beg = end;
- } else if (c == '\"') {
- if (inQuote) {
- tab[i++][1]= new String(ca, beg, end-beg);
- inQuote=false;
- do {
- end++;
- } while (end < len && (ca[end] == ' ' || ca[end] == ','));
- inKey=true;
- beg=end;
- } else {
- inQuote=true;
- end++;
- beg=end;
- }
- } else if (c == ' ' || c == ',') { // end key/val, of whatever we're in
- if (inQuote) {
- end++;
- continue;
- } else if (inKey) {
- tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase();
- } else {
- tab[i++][1] = (new String(ca, beg, end-beg));
- }
- while (end < len && (ca[end] == ' ' || ca[end] == ',')) {
- end++;
- }
- inKey = true;
- beg = end;
- } else {
- end++;
- }
- if (i == asize) {
- asize = asize * 2;
- String[][] ntab = new String[asize][2];
- System.arraycopy (tab, 0, ntab, 0, tab.length);
- tab = ntab;
- }
- }
- // get last key/val, if any
- if (--end > beg) {
- if (!inKey) {
- if (ca[end] == '\"') {
- tab[i++][1] = (new String(ca, beg, end-beg));
- } else {
- tab[i++][1] = (new String(ca, beg, end-beg+1));
- }
- } else {
- tab[i++][0] = (new String(ca, beg, end-beg+1)).toLowerCase();
- }
- } else if (end == beg) {
- if (!inKey) {
- if (ca[end] == '\"') {
- tab[i++][1] = String.valueOf(ca[end-1]);
- } else {
- tab[i++][1] = String.valueOf(ca[end]);
- }
- } else {
- tab[i++][0] = String.valueOf(ca[end]).toLowerCase();
- }
- }
- nkeys=i;
- }
-
- }
-
- public String findKey(int i) {
- if (i < 0 || i > asize)
- return null;
- return tab[i][0];
- }
-
- public String findValue(int i) {
- if (i < 0 || i > asize)
- return null;
- return tab[i][1];
- }
-
- public String findValue(String key) {
- return findValue(key, null);
- }
-
- public String findValue(String k, String Default) {
- if (k == null)
- return Default;
- k = k.toLowerCase();
- for (int i = 0; i < asize; ++i) {
- if (tab[i][0] == null) {
- return Default;
- } else if (k.equals(tab[i][0])) {
- return tab[i][1];
- }
- }
- return Default;
- }
-
- class ParserIterator implements Iterator {
- int index;
- boolean returnsValue; // or key
-
- ParserIterator (boolean returnValue) {
- returnsValue = returnValue;
- }
- public boolean hasNext () {
- return index<nkeys;
- }
- public Object next () {
- return tab[index++][returnsValue?1:0];
- }
- public void remove () {
- throw new UnsupportedOperationException ("remove not supported");
- }
- }
-
- public Iterator keys () {
- return new ParserIterator (false);
- }
-
- public Iterator values () {
- return new ParserIterator (true);
- }
-
- public String toString () {
- Iterator k = keys();
- StringBuffer sbuf = new StringBuffer();
- sbuf.append ("{size="+asize+" nkeys="+nkeys+" ");
- for (int i=0; k.hasNext(); i++) {
- String key = (String)k.next();
- String val = findValue (i);
- if (val != null && "".equals (val)) {
- val = null;
- }
- sbuf.append (" {"+key+(val==null?"":","+val)+"}");
- if (k.hasNext()) {
- sbuf.append (",");
- }
- }
- sbuf.append (" }");
- return new String (sbuf);
- }
-
- public int findInt(String k, int Default) {
- try {
- return Integer.parseInt(findValue(k, String.valueOf(Default)));
- } catch (Throwable t) {
- return Default;
- }
- }
- /*
- public static void main(String[] a) throws Exception {
- System.out.print("enter line to parse> ");
- System.out.flush();
- DataInputStream dis = new DataInputStream(System.in);
- String line = dis.readLine();
- HeaderParser p = new HeaderParser(line);
- for (int i = 0; i < asize; ++i) {
- if (p.findKey(i) == null) break;
- String v = p.findValue(i);
- System.out.println(i + ") " +p.findKey(i) + "="+v);
- }
- System.out.println("Done!");
-
- }
- */
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java b/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java
index e7e6ad0..410ba0a 100644
--- a/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java
+++ b/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java
@@ -45,11 +45,12 @@
/* URL jar file is a common JarFile subtype used for JarURLConnection */
public class URLJarFile extends JarFile {
- /*
- * Interface to be able to call retrieve() in plugin if
- * this variable is set.
- */
- private static URLJarFileCallBack callback = null;
+// Android-changed: Removed setCallBack(URLJarFileCallBack) and field callback (dead code).
+// /*
+// * Interface to be able to call retrieve() in plugin if
+// * this variable is set.
+// */
+// private static URLJarFileCallBack callback = null;
/* Controller of the Jar File's closing */
private URLJarFileCloseController closeController = null;
@@ -195,17 +196,18 @@
* cached JAR file object.
*/
private static JarFile retrieve(final URL url, final URLJarFileCloseController closeController) throws IOException {
- /*
- * See if interface is set, then call retrieve function of the class
- * that implements URLJarFileCallBack interface (sun.plugin - to
- * handle the cache failure for JARJAR file.)
- */
- if (callback != null)
- {
- return callback.retrieve(url);
- }
-
- else
+// Android-changed: Removed setCallBack(URLJarFileCallBack) and field callback (dead code).
+// /*
+// * See if interface is set, then call retrieve function of the class
+// * that implements URLJarFileCallBack interface (sun.plugin - to
+// * handle the cache failure for JARJAR file.)
+// */
+// if (callback != null)
+// {
+// return callback.retrieve(url);
+// }
+//
+// else
{
JarFile result = null;
@@ -239,15 +241,15 @@
}
}
- /*
- * Set the call back interface to call retrive function in sun.plugin
- * package if plugin is running.
- */
- public static void setCallBack(URLJarFileCallBack cb)
- {
- callback = cb;
- }
-
+// Android-changed: Removed setCallBack(URLJarFileCallBack) and field callback (dead code).
+// /*
+// * Set the call back interface to call retrive function in sun.plugin
+// * package if plugin is running.
+// */
+// public static void setCallBack(URLJarFileCallBack cb)
+// {
+// callback = cb;
+// }
private class URLJarFileEntry extends JarEntry {
private JarEntry je;
diff --git a/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFileCallBack.java b/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFileCallBack.java
deleted file mode 100644
index d55aeaf..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFileCallBack.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2001, 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.net.www.protocol.jar;
-
-import java.io.*;
-import java.net.*;
-import java.util.jar.*;
-
-
-/*
- * This interface is used to call back to sun.plugin package.
- */
-public interface URLJarFileCallBack
-{
- public JarFile retrieve (URL url) throws IOException;
-}
diff --git a/ojluni/src/main/java/sun/util/locale/provider/CalendarDataUtility.java b/ojluni/src/main/java/sun/util/locale/provider/CalendarDataUtility.java
index 509e760..30df227 100644
--- a/ojluni/src/main/java/sun/util/locale/provider/CalendarDataUtility.java
+++ b/ojluni/src/main/java/sun/util/locale/provider/CalendarDataUtility.java
@@ -43,6 +43,11 @@
*/
public class CalendarDataUtility {
+ private static final String ISLAMIC_CALENDAR = "islamic";
+ private static final String GREGORIAN_CALENDAR = "gregorian";
+ private static final String BUDDHIST_CALENDAR = "buddhist";
+ private static final String JAPANESE_CALENDAR = "japanese";
+
// No instantiation
private CalendarDataUtility() {
}
@@ -53,6 +58,25 @@
public static String retrieveFieldValueName(String id, int field, int value, int style,
Locale locale) {
// Android-changed: delegate to ICU.
+ if (field == Calendar.ERA) {
+ // For era the field value does not always equal the index into the names array.
+ switch (normalizeCalendarType(id)) {
+ // These calendars have only one era, but represented it by the value 1.
+ case BUDDHIST_CALENDAR:
+ case ISLAMIC_CALENDAR:
+ value -= 1;
+ break;
+ case JAPANESE_CALENDAR:
+ // CLDR contains full data for historical eras, java.time only supports the 4
+ // modern eras and numbers the modern eras starting with 1 (MEIJI). There are
+ // 232 historical eras in CLDR/ICU so to get the real offset, we add 231.
+ value += 231;
+ break;
+ default:
+ // Other eras use 0-based values (e.g. 0=BCE, 1=CE for gregorian).
+ break;
+ }
+ }
if (value < 0) {
return null;
}
@@ -69,14 +93,60 @@
return retrieveFieldValueName(id, field, value, style, locale);
}
+ // ALL_STYLES implies SHORT_FORMAT and all of these values.
+ private static int[] REST_OF_STYLES = {
+ SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE,
+ NARROW_FORMAT, NARROW_STANDALONE
+ };
+
public static Map<String, Integer> retrieveFieldValueNames(String id, int field, int style,
Locale locale) {
- // TODO: support ALL_STYLES
// Android-changed: delegate to ICU.
+ Map<String, Integer> names;
+ if (style == ALL_STYLES) {
+ names = retrieveFieldValueNamesImpl(id, field, SHORT_FORMAT, locale);
+ for (int st : REST_OF_STYLES) {
+ names.putAll(retrieveFieldValueNamesImpl(id, field, st, locale));
+ }
+ } else {
+ // specific style
+ names = retrieveFieldValueNamesImpl(id, field, style, locale);
+ }
+ return names.isEmpty() ? null : names;
+ }
+
+ private static Map<String, Integer> retrieveFieldValueNamesImpl(String id, int field, int style,
+ Locale locale) {
String[] names = getNames(id, field, style, locale);
+ int skipped = 0;
+ int offset = 0;
+ if (field == Calendar.ERA) {
+ // See retrieveFieldValueName() for explanation of this code and the values used.
+ switch (normalizeCalendarType(id)) {
+ case BUDDHIST_CALENDAR:
+ case ISLAMIC_CALENDAR:
+ offset = 1;
+ break;
+ case JAPANESE_CALENDAR:
+ skipped = 232;
+ offset = -231;
+ break;
+ default:
+ break;
+ }
+ }
Map<String, Integer> result = new LinkedHashMap<>();
- for (int i = 0; i < names.length; i++) {
- result.put(names[i], i);
+ for (int i = skipped; i < names.length; i++) {
+ if (names[i].isEmpty()) {
+ continue;
+ }
+
+ if (result.put(names[i], i + offset) != null) {
+ // Duplicate names indicate that the names would be ambiguous. Skip this style for
+ // ALL_STYLES. In other cases this results in null being returned in
+ // retrieveValueNames(), which is required by Calendar.getDisplayNames().
+ return new LinkedHashMap<>();
+ }
}
return result;
}
@@ -156,14 +226,14 @@
}
}
- static String normalizeCalendarType(String requestID) {
+ private static String normalizeCalendarType(String requestID) {
String type;
// Android-changed: normalize "gregory" to "gregorian", not the other way around.
// See android.icu.text.DateFormatSymbols.CALENDAR_CLASSES for reference.
if (requestID.equals("gregory") || requestID.equals("iso8601")) {
- type = "gregorian";
- } else if (requestID.startsWith("islamic")) {
- type = "islamic";
+ type = GREGORIAN_CALENDAR;
+ } else if (requestID.startsWith(ISLAMIC_CALENDAR)) {
+ type = ISLAMIC_CALENDAR;
} else {
type = requestID;
}
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKInstant.java b/ojluni/src/test/java/time/tck/java/time/TCKInstant.java
index ee3898e..3d89db5 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKInstant.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKInstant.java
@@ -106,7 +106,7 @@
import java.util.List;
import java.util.Locale;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -121,10 +121,13 @@
private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris");
private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
- private Instant TEST_12345_123456789;
+ // Android changed: This was originally non-static and initialized in @BeforeMethod,
+ // but @BeforeMethod is run after @DataProvider methods are run, so it only worked by accident,
+ // since multiple test methods were run and the first one did not require this value.
+ private static Instant TEST_12345_123456789;
- @BeforeMethod
- public void setUp() {
+ @BeforeClass
+ public static void setUp() {
TEST_12345_123456789 = Instant.ofEpochSecond(12345, 123456789);
}
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java b/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java
index 02e2f07..5670a46 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java
@@ -121,7 +121,7 @@
import java.util.Arrays;
import java.util.List;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import test.java.time.MockSimplePeriod;
@@ -138,16 +138,19 @@
private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris");
private static final ZoneId ZONE_GAZA = ZoneId.of("Asia/Gaza");
- private LocalDate TEST_2007_07_15;
- private long MAX_VALID_EPOCHDAYS;
- private long MIN_VALID_EPOCHDAYS;
- private LocalDate MAX_DATE;
- private LocalDate MIN_DATE;
- private Instant MAX_INSTANT;
- private Instant MIN_INSTANT;
+ // Android changed: These wer originally non-static and initialized in @BeforeMethod,
+ // but @BeforeMethod is run after @DataProvider methods are run, so it only worked by accident,
+ // since multiple test methods were run and the first one did not require this value.
+ private static LocalDate TEST_2007_07_15;
+ private static long MAX_VALID_EPOCHDAYS;
+ private static long MIN_VALID_EPOCHDAYS;
+ private static LocalDate MAX_DATE;
+ private static LocalDate MIN_DATE;
+ private static Instant MAX_INSTANT;
+ private static Instant MIN_INSTANT;
- @BeforeMethod
- public void setUp() {
+ @BeforeClass
+ public static void setUp() {
TEST_2007_07_15 = LocalDate.of(2007, 7, 15);
LocalDate max = LocalDate.MAX;
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java b/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java
index f79e8fc..a695803 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java
@@ -126,7 +126,7 @@
import java.util.Iterator;
import java.util.List;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -139,7 +139,10 @@
private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris");
- private LocalTime TEST_12_30_40_987654321;
+ // Android changed: This was originally non-static and initialized in @BeforeMethod,
+ // but @BeforeMethod is run after @DataProvider methods are run, so it only worked by accident,
+ // since multiple test methods were run and the first one did not require this value.
+ private static LocalTime TEST_12_30_40_987654321;
private static final TemporalUnit[] INVALID_UNITS;
static {
@@ -147,8 +150,8 @@
INVALID_UNITS = set.toArray(new TemporalUnit[set.size()]);
}
- @BeforeMethod
- public void setUp() {
+ @BeforeClass
+ public static void setUp() {
TEST_12_30_40_987654321 = LocalTime.of(12, 30, 40, 987654321);
}
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKMonthDay.java b/ojluni/src/test/java/time/tck/java/time/TCKMonthDay.java
index 99a7116..a9214e4 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKMonthDay.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKMonthDay.java
@@ -94,7 +94,7 @@
import java.util.List;
import java.util.Set;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -104,10 +104,13 @@
@Test
public class TCKMonthDay extends AbstractDateTimeTest {
- private MonthDay TEST_07_15;
+ // Android changed: This was originally non-static and initialized in @BeforeMethod,
+ // but @BeforeMethod is run after @DataProvider methods are run, so it only worked by accident,
+ // since multiple test methods were run and the first one did not require this value.
+ private static MonthDay TEST_07_15;
- @BeforeMethod
- public void setUp() {
+ @BeforeClass
+ public static void setUp() {
TEST_07_15 = MonthDay.of(7, 15);
}
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java b/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java
index b77b7a8..4849f06 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java
@@ -139,7 +139,7 @@
import java.util.Arrays;
import java.util.List;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import test.java.time.MockSimplePeriod;
@@ -156,10 +156,14 @@
private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
private static final ZoneOffset OFFSET_MONE = ZoneOffset.ofHours(-1);
private static final ZoneOffset OFFSET_MTWO = ZoneOffset.ofHours(-2);
- private OffsetDateTime TEST_2008_6_30_11_30_59_000000500;
- @BeforeMethod
- public void setUp() {
+ // Android changed: This was originally non-static and initialized in @BeforeMethod,
+ // but @BeforeMethod is run after @DataProvider methods are run, so it only worked by accident,
+ // since multiple test methods were run and the first one did not require this value.
+ private static OffsetDateTime TEST_2008_6_30_11_30_59_000000500;
+
+ @BeforeClass
+ public static void setUp() {
TEST_2008_6_30_11_30_59_000000500 = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 500, OFFSET_PONE);
}
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java b/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java
index d373be4..b195492 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java
@@ -122,7 +122,7 @@
import java.util.Arrays;
import java.util.List;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import test.java.time.MockSimplePeriod;
@@ -137,10 +137,14 @@
private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
private static final LocalDate DATE = LocalDate.of(2008, 12, 3);
- private OffsetTime TEST_11_30_59_500_PONE;
- @BeforeMethod
- public void setUp() {
+ // Android changed: This was originally non-static and initialized in @BeforeMethod,
+ // but @BeforeMethod is run after @DataProvider methods are run, so it only worked by accident,
+ // since multiple test methods were run and the first one did not require this value.
+ private static OffsetTime TEST_11_30_59_500_PONE;
+
+ @BeforeClass
+ public static void setUp() {
TEST_11_30_59_500_PONE = OffsetTime.of(11, 30, 59, 500, OFFSET_PONE);
}
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKYearMonth.java b/ojluni/src/test/java/time/tck/java/time/TCKYearMonth.java
index e922f72..1964db6 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKYearMonth.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKYearMonth.java
@@ -110,7 +110,7 @@
import java.util.List;
import java.util.Set;
-import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -120,10 +120,13 @@
@Test
public class TCKYearMonth extends AbstractDateTimeTest {
- private YearMonth TEST_2008_06;
+ // Android changed: This was originally non-static and initialized in @BeforeMethod,
+ // but @BeforeMethod is run after @DataProvider methods are run, so it only worked by accident,
+ // since multiple test methods were run and the first one did not require this value.
+ private static YearMonth TEST_2008_06;
- @BeforeMethod
- public void setUp() {
+ @BeforeClass
+ public static void setUp() {
TEST_2008_06 = YearMonth.of(2008, 6);
}
diff --git a/ojluni/src/test/java/time/tck/java/time/format/TCKFormatStyle.java b/ojluni/src/test/java/time/tck/java/time/format/TCKFormatStyle.java
index 1175673..bd38d51 100644
--- a/ojluni/src/test/java/time/tck/java/time/format/TCKFormatStyle.java
+++ b/ojluni/src/test/java/time/tck/java/time/format/TCKFormatStyle.java
@@ -93,15 +93,16 @@
@DataProvider(name="formatStyle")
Object[][] data_formatStyle() {
return new Object[][] {
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.FULL, "Tuesday, October 2, 2001 1:02:03 AM CEST Europe/Paris"},
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.LONG, "October 2, 2001 1:02:03 AM CEST Europe/Paris"},
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.MEDIUM, "Oct 2, 2001 1:02:03 AM Europe/Paris"},
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.SHORT, "10/2/01 1:02 AM Europe/Paris"},
+ // Android-changed: date/time patterns changed in new CLDR; adapt to UK locale.
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.FULL, "Tuesday, 2 October 2001 at 01:02:03 Central European Summer Time Europe/Paris"},
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.LONG, "2 October 2001 at 01:02:03 CEST Europe/Paris"},
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.MEDIUM, "2 Oct 2001, 01:02:03 Europe/Paris"},
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), ZONEID_PARIS), FormatStyle.SHORT, "02/10/2001, 01:02 Europe/Paris"},
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.FULL, "Tuesday, October 2, 2001 1:02:03 AM +02:00 +02:00"},
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.LONG, "October 2, 2001 1:02:03 AM +02:00 +02:00"},
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.MEDIUM, "Oct 2, 2001 1:02:03 AM +02:00"},
- {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.SHORT, "10/2/01 1:02 AM +02:00"},
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.FULL, "Tuesday, 2 October 2001 at 01:02:03 +02:00 +02:00"},
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.LONG, "2 October 2001 at 01:02:03 +02:00 +02:00"},
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.MEDIUM, "2 Oct 2001, 01:02:03 +02:00"},
+ {ZonedDateTime.of(LocalDateTime.of(2001, 10, 2, 1, 2, 3), OFFSET_PTWO), FormatStyle.SHORT, "02/10/2001, 01:02 +02:00"},
};
}
@@ -109,7 +110,8 @@
public void test_formatStyle(Temporal temporal, FormatStyle style, String formattedStr) {
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeFormatter formatter = builder.appendLocalized(style, style).appendLiteral(" ").appendZoneOrOffsetId().toFormatter();
- formatter = formatter.withLocale(Locale.US);
+ // Android-changed: Use a locale that actually uses "CEST" as short form of Europe/Paris.
+ formatter = formatter.withLocale(Locale.UK);
assertEquals(formatter.format(temporal), formattedStr);
}
}
diff --git a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java
index 19f8239..dc4860e 100644
--- a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java
+++ b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java
@@ -372,7 +372,8 @@
ZoneOffsetTransitionRule in = rules.get(0);
assertEquals(in.getMonth(), Month.MARCH);
- assertEquals(in.getDayOfMonthIndicator(), 25); // optimized from -1
+ // Android changed: check for -1, which matches the data, we don't do the "optimization"
+ assertEquals(in.getDayOfMonthIndicator(), -1); // optimized from -1
assertEquals(in.getDayOfWeek(), DayOfWeek.SUNDAY);
assertEquals(in.getLocalTime(), LocalTime.of(1, 0));
assertEquals(in.getTimeDefinition(), TimeDefinition.UTC);
@@ -382,7 +383,8 @@
ZoneOffsetTransitionRule out = rules.get(1);
assertEquals(out.getMonth(), Month.OCTOBER);
- assertEquals(out.getDayOfMonthIndicator(), 25); // optimized from -1
+ // Android changed: check for -1, which matches the data, we don't do the "optimization"
+ assertEquals(out.getDayOfMonthIndicator(), -1); // optimized from -1
assertEquals(out.getDayOfWeek(), DayOfWeek.SUNDAY);
assertEquals(out.getLocalTime(), LocalTime.of(1, 0));
assertEquals(out.getTimeDefinition(), TimeDefinition.UTC);
diff --git a/ojluni/src/test/java/time/test/java/time/chrono/TestServiceLoader.java b/ojluni/src/test/java/time/test/java/time/chrono/TestServiceLoader.java
index b64f8f4..2e65b8e 100644
--- a/ojluni/src/test/java/time/test/java/time/chrono/TestServiceLoader.java
+++ b/ojluni/src/test/java/time/test/java/time/chrono/TestServiceLoader.java
@@ -77,7 +77,10 @@
@Test
public void test_copticServiceLoader() {
Map<String, Chronology> chronos = new HashMap<>();
- ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class, null);
+ // Android-changed: This test assumes that the system classloader sees all test classes.
+ // That assumption is untrue, when run in CTS. Use this class's classloader instead.
+ ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class,
+ getClass().getClassLoader());
for (Chronology chrono : loader) {
chronos.put(chrono.getId(), chrono);
}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
index 16a7d6e..a13630a 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
@@ -903,60 +903,61 @@
//-----------------------------------------------------------------------
@DataProvider(name="localePatterns")
Object[][] localizedDateTimePatterns() {
+ // Android-changed: Adapt for changes since old CLDR version this tests were written for.
return new Object[][] {
- {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, yyyy h:mm:ss a z"},
- {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "MMMM d, yyyy h:mm:ss a z"},
- {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "MMM d, yyyy h:mm:ss a"},
- {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "M/d/yy h:mm a"},
- {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, yyyy"},
- {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.US, "MMMM d, yyyy"},
- {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.US, "MMM d, yyyy"},
+ {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, y 'at' h:mm:ss a zzzz"},
+ {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "MMMM d, y 'at' h:mm:ss a z"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "MMM d, y, h:mm:ss a"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "M/d/yy, h:mm a"},
+ {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, y"},
+ {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.US, "MMMM d, y"},
+ {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.US, "MMM d, y"},
{FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.US, "M/d/yy"},
- {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"},
+ {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a zzzz"},
{null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"},
{null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a"},
{null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "h:mm a"},
// French Locale and ISO Chronology
- {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM yyyy HH' h 'mm z"},
- {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM yyyy HH:mm:ss z"},
- {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM yyyy HH:mm:ss"},
- {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/yy HH:mm"},
- {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM yyyy"},
- {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM yyyy"},
- {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM yyyy"},
- {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/yy"},
- {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH' h 'mm z"},
+ {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y 'à' HH:mm:ss zzzz"},
+ {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y 'à' HH:mm:ss z"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y 'à' HH:mm:ss"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"},
+ {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"},
+ {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"},
+ {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"},
+ {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"},
+ {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"},
{null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"},
{null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"},
{null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"},
// Japanese Locale and JapaneseChronology
- {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy'\u5e74'M'\u6708'd'\u65e5' H'\u6642'mm'\u5206'ss'\u79d2' z"},
- {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd H:mm:ss z"},
- {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd H:mm:ss"},
- {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd H:mm"},
- {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy'\u5e74'M'\u6708'd'\u65e5'"},
- {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd"},
- {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd"},
- {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy.MM.dd"},
- {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H'\u6642'mm'\u5206'ss'\u79d2' z"},
+ {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"},
+ {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"},
+ {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
+ {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
+ {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
+ {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"},
+ {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"},
{null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"},
{null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"},
{null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"},
// Chinese Local and Chronology
- {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE ahh'\u65f6'mm'\u5206'ss'\u79d2' z"},
- {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ahh'\u65f6'mm'\u5206'ss'\u79d2'"},
- {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d H:mm:ss"},
- {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d ah:mm"},
+ {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"},
+ {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"},
+ {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"},
+ {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"},
{FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
{FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
- {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d"},
- {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy-M-d"},
- {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "ahh'\u65f6'mm'\u5206'ss'\u79d2' z"},
- {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "ahh'\u65f6'mm'\u5206'ss'\u79d2'"},
- {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "H:mm:ss"},
+ {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
+ {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"},
+ {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"},
+ {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"},
+ {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"},
{null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"},
};
}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java
index aebccfd..7628eeb 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java
@@ -94,13 +94,14 @@
{DAY_OF_WEEK, 6, TextStyle.SHORT, enUS, "Sat"},
{DAY_OF_WEEK, 7, TextStyle.SHORT, enUS, "Sun"},
- {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "Seg"},
- {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "Ter"},
- {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "Qua"},
- {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "Qui"},
- {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "Sex"},
- {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "S\u00E1b"},
- {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "Dom"},
+ // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower
+ {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg"},
+ {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter"},
+ {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua"},
+ {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui"},
+ {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex"},
+ {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b"},
+ {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom"},
{DAY_OF_WEEK, 1, TextStyle.FULL, enUS, "Monday"},
{DAY_OF_WEEK, 2, TextStyle.FULL, enUS, "Tuesday"},
@@ -110,13 +111,14 @@
{DAY_OF_WEEK, 6, TextStyle.FULL, enUS, "Saturday"},
{DAY_OF_WEEK, 7, TextStyle.FULL, enUS, "Sunday"},
- {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "Segunda-feira"},
- {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "Ter\u00E7a-feira"},
- {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "Quarta-feira"},
- {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "Quinta-feira"},
- {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "Sexta-feira"},
- {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "S\u00E1bado"},
- {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "Domingo"},
+ // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower
+ {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "segunda-feira"},
+ {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "ter\u00E7a-feira"},
+ {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "quarta-feira"},
+ {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "quinta-feira"},
+ {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "sexta-feira"},
+ {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "s\u00E1bado"},
+ {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "domingo"},
{MONTH_OF_YEAR, 1, TextStyle.SHORT, enUS, "Jan"},
{MONTH_OF_YEAR, 2, TextStyle.SHORT, enUS, "Feb"},
@@ -157,18 +159,19 @@
{MONTH_OF_YEAR, 11, TextStyle.FULL, enUS, "November"},
{MONTH_OF_YEAR, 12, TextStyle.FULL, enUS, "December"},
- {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "Janeiro"},
- {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "Fevereiro"},
- {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "Mar\u00E7o"},
- {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "Abril"},
- {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "Maio"},
- {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "Junho"},
- {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "Julho"},
- {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "Agosto"},
- {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "Setembro"},
- {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "Outubro"},
- {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "Novembro"},
- {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "Dezembro"},
+ // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower
+ {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "janeiro"},
+ {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "fevereiro"},
+ {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "mar\u00E7o"},
+ {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "abril"},
+ {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "maio"},
+ {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "junho"},
+ {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "julho"},
+ {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "agosto"},
+ {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "setembro"},
+ {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "outubro"},
+ {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "novembro"},
+ {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "dezembro"},
{AMPM_OF_DAY, 0, TextStyle.SHORT, enUS, "AM"},
{AMPM_OF_DAY, 1, TextStyle.SHORT, enUS, "PM"},
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java b/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
index 6747cdc..6609f2c 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
@@ -76,20 +76,25 @@
return new Object[][] {
// Chronology, Format Locale, Numbering Locale, ChronoLocalDate, expected string
{ JAPANESE, Locale.JAPANESE, Locale.JAPANESE, JAPANESE.date(IsoDate),
- "\u5e73\u621025\u5e742\u670811\u65e5" }, // Japanese Heisei 25-02-11
+ "\u5e73\u621025\u5e742\u670811\u65e5\u6708\u66dc\u65e5" }, // Japanese Heisei 25-02-11
+ // Android-changed: requesting arabic numbering actually produces arabic digits. Also
+ // new CLDR patterns include the era. Test Arabic locale with ASCII digits below.
{ HIJRAH, ARABIC, ARABIC, HIJRAH.date(IsoDate),
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c \u0661 \u0631\u0628\u064a\u0639 "
+ + "\u0627\u0644\u0622\u062e\u0631\u060c \u0661\u0664\u0663\u0664 \u0647\u0640" }, // Hijrah AH 1434-04-01 (Mon)
+ { HIJRAH, ARABIC, Locale.ENGLISH, HIJRAH.date(IsoDate),
"\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c 1 \u0631\u0628\u064a\u0639 "
- + "\u0627\u0644\u0622\u062e\u0631 1434" }, // Hijrah AH 1434-04-01 (Mon)
+ + "\u0627\u0644\u0622\u062e\u0631\u060c 1434 \u0647\u0640" }, // Hijrah AH 1434-04-01 (Mon)
{ MINGUO, Locale.TAIWAN, Locale.TAIWAN, MINGUO.date(IsoDate),
- "\u6c11\u570b102\u5e742\u670811\u65e5\u661f\u671f\u4e00" }, // Minguo ROC 102-02-11 (Mon)
+ "\u6c11\u570b102\u5e742\u670811\u65e5 \u661f\u671f\u4e00" }, // Minguo ROC 102-02-11 (Mon)
{ BUDDHIST, thTH, thTH, BUDDHIST.date(IsoDate),
- "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48"
- + " 11 \u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c"
- + " \u0e1e.\u0e28. 2556" }, // ThaiBuddhist BE 2556-02-11
+ "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48 "
+ + "11 \u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c "
+ + "\u0e1e.\u0e28. 2556" }, // ThaiBuddhist BE 2556-02-11
{ BUDDHIST, thTH, thTHTH, BUDDHIST.date(IsoDate),
"\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48 \u0e51\u0e51 "
- + "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c \u0e1e.\u0e28. "
- + "\u0e52\u0e55\u0e55\u0e56" }, // ThaiBuddhist BE 2556-02-11 (with Thai digits)
+ + "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c "
+ + "\u0e1e.\u0e28. \u0e52\u0e55\u0e55\u0e56" }, // ThaiBuddhist BE 2556-02-11 (with Thai digits)
};
}
@@ -108,23 +113,24 @@
Object[][] chronoNamesData() {
return new Object[][] {
// Chronology, Locale, Chronology Name
- { ISO8601, Locale.ENGLISH, "ISO" }, // No data in CLDR; Use Id.
+ // Android-changed: CLDR data has changed.
+ { ISO8601, Locale.ENGLISH, "ISO-8601 Calendar" },
{ BUDDHIST, Locale.ENGLISH, "Buddhist Calendar" },
- { HIJRAH, Locale.ENGLISH, "Islamic Umm al-Qura Calendar" }, // JDK-8015986
+ { HIJRAH, Locale.ENGLISH, "Islamic Calendar (Umm al-Qura)" },
{ JAPANESE, Locale.ENGLISH, "Japanese Calendar" },
{ MINGUO, Locale.ENGLISH, "Minguo Calendar" },
- { ISO8601, Locale.JAPANESE, "ISO" }, // No data in CLDR; Use Id.
+ { ISO8601, Locale.JAPANESE, "ISO-8601" },
{ JAPANESE, Locale.JAPANESE, "\u548c\u66a6" },
- { BUDDHIST, Locale.JAPANESE, "\u30bf\u30a4\u4ecf\u6559\u66a6" },
+ { BUDDHIST, Locale.JAPANESE, "\u4ecf\u66a6" },
- { ISO8601, thTH, "ISO" }, // No data in CLDR; Use Id.
+ { ISO8601, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19 ISO-8601" },
{ JAPANESE, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e0d\u0e35\u0e48\u0e1b\u0e38\u0e48\u0e19" },
{ BUDDHIST, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e1e\u0e38\u0e17\u0e18" },
- { HIJRAH, ARABIC, "\u0644\u062a\u0642\u0648\u064a\u0645 "
- + "\u0627\u0644\u0647\u062c\u0631\u064a\u060c "
- + "\u0623\u0645 \u0627\u0644\u0642\u0631\u0649" }, // JDK-8015986
+ { HIJRAH, ARABIC, "\u0627\u0644\u062a\u0642\u0648\u064a\u0645 "
+ + "\u0627\u0644\u0625\u0633\u0644\u0627\u0645\u064a "
+ + "(\u0623\u0645 \u0627\u0644\u0642\u0631\u0649)" }, // JDK-8015986
};
}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java b/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java
index 07bd214..721f337 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java
@@ -208,10 +208,11 @@
Object[][] providerStandaloneText() {
// Locale, TemporalField, TextStyle, expected value, input text
return new Object[][] {
- {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 1, "\u042f\u043d\u0432\u0430\u0440\u044c"},
- {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 12, "\u0414\u0435\u043a\u0430\u0431\u0440\u044c"},
- {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 1, "\u042f\u043d\u0432."},
- {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0414\u0435\u043a."},
+ // Android-changed: CLDR provides russian days/months in lower-case and with a fullstop.
+ {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 1, "\u044f\u043d\u0432\u0430\u0440\u044c" },
+ {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 12, "\u0434\u0435\u043a\u0430\u0431\u0440\u044c" },
+ {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 1, "\u044f\u043d\u0432." },
+ {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0434\u0435\u043a." },
{FINNISH, DAY_OF_WEEK, TextStyle.FULL_STANDALONE, 2, "tiistai"},
{FINNISH, DAY_OF_WEEK, TextStyle.SHORT_STANDALONE, 2, "ti"},
};
@@ -236,10 +237,11 @@
Object[][] providerLenientText() {
// Locale, TemporalField, expected value, input text
return new Object[][] {
- {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f"}, // full format
- {RUSSIAN, MONTH_OF_YEAR, 1, "\u042f\u043d\u0432\u0430\u0440\u044c"}, // full standalone
- {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432"}, // short format
- {RUSSIAN, MONTH_OF_YEAR, 1, "\u042f\u043d\u0432."}, // short standalone
+ // Android-changed: CLDR provides russian months in lower-case and with a fullstop.
+ {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f" }, // full format
+ {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044c" }, // full standalone
+ {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432." }, // short format
+ {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432." }, // short standalone
};
}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java b/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java
index 662288c..19e6421 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java
@@ -235,8 +235,9 @@
return new Object[][] {
// standalone names for 2013-01-01 (Tue)
// Locale, TemporalField, TextStyle, expected text
- {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, "\u042f\u043d\u0432\u0430\u0440\u044c"},
- {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u042f\u043d\u0432."},
+ // Android-changed: CLDR uses lower case for russian month names.
+ {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, "\u044f\u043d\u0432\u0430\u0440\u044c"},
+ {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u044f\u043d\u0432."},
{FINNISH, DAY_OF_WEEK, TextStyle.FULL_STANDALONE, "tiistai"},
{FINNISH, DAY_OF_WEEK, TextStyle.SHORT_STANDALONE, "ti"},
};
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
index 94b6096..4855740 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
@@ -46,6 +46,7 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import android.icu.impl.ZoneMeta;
/*
* @test
@@ -67,7 +68,8 @@
public void test_printText() {
Random r = RandomFactory.getRandom();
- int N = 8;
+ // Android changed: only run one iteration.
+ int N = 1;
Locale[] locales = Locale.getAvailableLocales();
Set<String> zids = ZoneRulesProvider.getAvailableZoneIds();
ZonedDateTime zdt = ZonedDateTime.now();
@@ -76,14 +78,29 @@
while (N-- > 0) {
zdt = zdt.withDayOfYear(r.nextInt(365) + 1)
.with(ChronoField.SECOND_OF_DAY, r.nextInt(86400));
- for (String zid : zids) {
- if (zid.equals("ROC") || zid.startsWith("Etc/GMT")) {
- continue; // TBD: match jdk behavior?
+ // Android-changed: loop over locales first to speed up test. TimeZoneNames are cached
+ // per locale, but the cache only holds the most recently used locales.
+ for (Locale locale : locales) {
+ // Android-changed: "ji" isn't correctly aliased to "yi", see http//b/8634320.
+ if (locale.getLanguage().equals("ji")) {
+ continue;
}
- zdt = zdt.withZoneSameLocal(ZoneId.of(zid));
- TimeZone tz = TimeZone.getTimeZone(zid);
- boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli()));
- for (Locale locale : locales) {
+ for (String zid : zids) {
+ if (zid.equals("ROC") || zid.startsWith("Etc/GMT")) {
+ continue; // TBD: match jdk behavior?
+ }
+ // Android-changed (http://b/33197219): TimeZone.getDisplayName() for
+ // non-canonical time zones are not correct.
+ if (!zid.equals(ZoneMeta.getCanonicalCLDRID(zid))) {
+ continue;
+ }
+ zdt = zdt.withZoneSameLocal(ZoneId.of(zid));
+ TimeZone tz = TimeZone.getTimeZone(zid);
+ // Android-changed: We don't have long names for GMT.
+ if (tz.getID().equals("GMT")) {
+ continue;
+ }
+ boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli()));
printText(locale, zdt, TextStyle.FULL, tz,
tz.getDisplayName(isDST, TimeZone.LONG, locale));
printText(locale, zdt, TextStyle.SHORT, tz,
@@ -95,6 +112,10 @@
private void printText(Locale locale, ZonedDateTime zdt, TextStyle style, TimeZone zone, String expected) {
String result = getFormatter(locale, style).format(zdt);
+ // Android-changed: TimeZone.getDisplayName() will never return "GMT".
+ if (result.startsWith("GMT") && expected.equals("GMT+00:00")) {
+ return;
+ }
if (!result.equals(expected)) {
if (result.equals("FooLocation")) { // from rules provider test if same vm
return;
@@ -107,6 +128,8 @@
assertEquals(result, expected);
}
+ // Android-changed: disable test as it doesn't assert anything and produces a lot of output.
+ @Test(enabled = false)
public void test_ParseText() {
Locale[] locales = new Locale[] { Locale.ENGLISH, Locale.JAPANESE, Locale.FRENCH };
Set<String> zids = ZoneRulesProvider.getAvailableZoneIds();
diff --git a/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java b/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java
index 41d464c..4946ccd 100644
--- a/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java
+++ b/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java
@@ -123,7 +123,8 @@
public void test_IsoFields_week_based_year() {
Locale locale = Locale.US;
String name = IsoFields.WEEK_OF_WEEK_BASED_YEAR.getDisplayName(locale);
- assertEquals(name, "Week");
+ // Android-changed: week is lower-case in CLDR.
+ assertEquals(name, "week");
}
@Test(expectedExceptions=NullPointerException.class)
@@ -136,7 +137,8 @@
Locale locale = Locale.US;
TemporalField weekOfYearField = WeekFields.SUNDAY_START.weekOfYear();
String name = weekOfYearField.getDisplayName(locale);
- assertEquals(name, "Week");
+ // Android-changed: week is lower-case in CLDR.
+ assertEquals(name, "week");
}
@Test(expectedExceptions=NullPointerException.class)
diff --git a/ojluni/src/test/java/time/test/java/util/TestFormatter.java b/ojluni/src/test/java/time/test/java/util/TestFormatter.java
index 67a73ce..afd5fc4 100644
--- a/ojluni/src/test/java/time/test/java/util/TestFormatter.java
+++ b/ojluni/src/test/java/time/test/java/util/TestFormatter.java
@@ -92,7 +92,8 @@
Chronology chrono = Chronology.ofLocale(calLocale);
ChronoLocalDate now = chrono.dateNow();
ChronoLocalDateTime<?> ldt0 = now.atTime(LocalTime.now());
- ChronoZonedDateTime<?> zdt0 = ldt0.atZone(ZoneId.systemDefault());
+ // Android changed: use hard-coded zone id instead of system default.
+ ChronoZonedDateTime<?> zdt0 = ldt0.atZone(ZoneId.of("America/Los_Angeles"));
ChronoZonedDateTime<?>[] zdts = new ChronoZonedDateTime<?>[] {
zdt0,
zdt0.withZoneSameLocal(ZoneId.of("UTC")),
@@ -105,9 +106,16 @@
zdt = zdt.with(ChronoField.DAY_OF_YEAR, (r.nextInt(365) + 1))
.with(ChronoField.SECOND_OF_DAY, r.nextInt(86400));
Instant instant = zdt.toInstant();
- Calendar cal = Calendar.getInstance(calLocale);
+ // Android changed: Calendar.getInstance() only returns GregorianCalendar.
+ // Manually get a JapaneseImperialCalendar for the test.
+ TimeZone tz = TimeZone.getTimeZone(zdt.getZone());
+ Calendar cal;
+ if (calLocale.getLanguage().equals("ja")) {
+ cal = Calendar.getJapanesImperialInstance(tz, calLocale);
+ } else {
+ cal = Calendar.getInstance(tz, calLocale);
+ }
cal.setTimeInMillis(instant.toEpochMilli());
- cal.setTimeZone(TimeZone.getTimeZone(zdt.getZone()));
for (Locale locale : locales) {
for (String fmtStr : fmtStrDate) {
testDate(fmtStr, locale, zdt, cal);
@@ -197,18 +205,22 @@
}
private String toZoneIdStr(String expected) {
- return expected.replaceAll("(?:GMT|UTC)(?<off>[+\\-]?[0-9]{2}:[0-9]{2})", "${off}");
+ // Android changed: java.util.Calendar and java.time types are formatted identically.
+ return expected;
}
private String toZoneOffsetStr(String expected) {
- return expected.replaceAll("(?:GMT|UTC)(?<off>[+\\-]?[0-9]{2}:[0-9]{2})", "${off}")
- .replaceAll("GMT|UTC|UT", "Z");
+ // Android changed: Android Matcher doesn't support named groups. Also GMT/Z is formatted as
+ // "GMT+00:00".
+ return expected.replaceAll("GMT(?:\\+00:00)|UTC|UT", "Z")
+ .replaceAll("(?:GMT|UTC)([+\\-]?[0-9]{2}:[0-9]{2})", "$1");
}
private void testZoneId(Locale locale, ChronoZonedDateTime<?> zdt, Calendar cal) {
String fmtStr = "z:[%tz] z:[%1$Tz] Z:[%1$tZ] Z:[%1$TZ]";
printFmtStr(locale, fmtStr);
- String expected = toZoneIdStr(test(fmtStr, locale, null, cal));
+ String calOutput = test(fmtStr, locale, null, cal);
+ String expected = toZoneIdStr(calOutput);
test(fmtStr, locale, expected, zdt);
// get a new cal with fixed tz
Calendar cal0 = Calendar.getInstance();
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 6907dde..a64b131 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1409,7 +1409,6 @@
ojluni/src/main/java/sun/net/ftp/FtpReplyCode.java \
ojluni/src/main/java/sun/net/ftp/impl/DefaultFtpClientProvider.java \
ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java \
- ojluni/src/main/java/sun/net/InetAddressCachePolicy.java \
ojluni/src/main/java/sun/net/NetHooks.java \
ojluni/src/main/java/sun/net/NetProperties.java \
ojluni/src/main/java/sun/net/NetworkClient.java \
@@ -1418,10 +1417,7 @@
ojluni/src/main/java/sun/net/ProgressMeteringPolicy.java \
ojluni/src/main/java/sun/net/ProgressMonitor.java \
ojluni/src/main/java/sun/net/ProgressSource.java \
- ojluni/src/main/java/sun/net/RegisteredDomain.java \
ojluni/src/main/java/sun/net/ResourceManager.java \
- ojluni/src/main/java/sun/net/smtp/SmtpClient.java \
- ojluni/src/main/java/sun/net/smtp/SmtpProtocolException.java \
ojluni/src/main/java/sun/net/SocksProxy.java \
ojluni/src/main/java/sun/net/spi/DefaultProxySelector.java \
ojluni/src/main/java/sun/net/spi/nameservice/NameServiceDescriptor.java \
@@ -1429,10 +1425,8 @@
ojluni/src/main/java/sun/net/TelnetInputStream.java \
ojluni/src/main/java/sun/net/TelnetOutputStream.java \
ojluni/src/main/java/sun/net/TelnetProtocolException.java \
- ojluni/src/main/java/sun/net/TransferProtocolClient.java \
ojluni/src/main/java/sun/net/util/IPAddressUtil.java \
ojluni/src/main/java/sun/net/util/URLUtil.java \
- ojluni/src/main/java/sun/net/www/HeaderParser.java \
ojluni/src/main/java/sun/net/www/MessageHeader.java \
ojluni/src/main/java/sun/net/www/MeteredStream.java \
ojluni/src/main/java/sun/net/www/ParseUtil.java \
@@ -1445,7 +1439,6 @@
ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java \
ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java \
ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java \
- ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFileCallBack.java \
ojluni/src/main/java/sun/nio/ByteBuffered.java \
ojluni/src/main/java/sun/nio/ch/AbstractPollArrayWrapper.java \
ojluni/src/main/java/sun/nio/ch/AbstractPollSelectorImpl.java \
diff --git a/tzdata/tools2/src/main/libcore/tzdata/update2/tools/CreateTimeZoneBundle.java b/tzdata/tools2/src/main/libcore/tzdata/update2/tools/CreateTimeZoneBundle.java
index 6297663..4013326 100644
--- a/tzdata/tools2/src/main/libcore/tzdata/update2/tools/CreateTimeZoneBundle.java
+++ b/tzdata/tools2/src/main/libcore/tzdata/update2/tools/CreateTimeZoneBundle.java
@@ -23,6 +23,7 @@
import java.io.OutputStream;
import java.io.Reader;
import java.util.Properties;
+import libcore.tzdata.update2.BundleVersion;
import libcore.tzdata.update2.TimeZoneBundle;
/**
@@ -48,9 +49,13 @@
System.exit(2);
}
Properties p = loadProperties(f);
+ BundleVersion bundleVersion = new BundleVersion(
+ BundleVersion.CURRENT_FORMAT_MAJOR_VERSION,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION,
+ getMandatoryProperty(p, "rules.version"),
+ Integer.parseInt(getMandatoryProperty(p, "revision")));
TimeZoneBundleBuilder builder = new TimeZoneBundleBuilder()
- .setRulesVersion(getMandatoryProperty(p, "rules.version"))
- .setAndroidRevision(getMandatoryProperty(p, "android.revision"))
+ .setBundleVersion(bundleVersion)
.setTzData(getMandatoryPropertyFile(p, "bionic.file"))
.setIcuData(getMandatoryPropertyFile(p, "icu.file"));
diff --git a/tzdata/tools2/src/main/libcore/tzdata/update2/tools/TimeZoneBundleBuilder.java b/tzdata/tools2/src/main/libcore/tzdata/update2/tools/TimeZoneBundleBuilder.java
index 39aa496..3f7c323 100644
--- a/tzdata/tools2/src/main/libcore/tzdata/update2/tools/TimeZoneBundleBuilder.java
+++ b/tzdata/tools2/src/main/libcore/tzdata/update2/tools/TimeZoneBundleBuilder.java
@@ -31,31 +31,28 @@
*/
public final class TimeZoneBundleBuilder {
- private String bundleFormatVersion = BundleVersion.FULL_BUNDLE_FORMAT_VERSION;
- private String rulesVersion;
- private String androidRevision;
+ private BundleVersion bundleVersion;
private byte[] tzData;
private byte[] icuData;
- // For use in tests.
- public TimeZoneBundleBuilder setBundleVersionForTests(String bundleVersion) {
- this.bundleFormatVersion = bundleVersion;
- return this;
- }
-
- public TimeZoneBundleBuilder setRulesVersion(String rulesVersion) {
- this.rulesVersion = rulesVersion;
- return this;
- }
-
- public TimeZoneBundleBuilder setAndroidRevision(String androidRevision) {
- this.androidRevision = androidRevision;
+ public TimeZoneBundleBuilder setBundleVersion(BundleVersion bundleVersion) {
+ this.bundleVersion = bundleVersion;
return this;
}
public TimeZoneBundleBuilder clearVersionForTests() {
// This has the effect of omitting the version file in buildUnvalidated().
- this.bundleFormatVersion = null;
+ this.bundleVersion = null;
+ return this;
+ }
+
+ public TimeZoneBundleBuilder replaceFormatVersionForTests(int majorVersion, int minorVersion) {
+ try {
+ bundleVersion = new BundleVersion(
+ majorVersion, minorVersion, bundleVersion.rulesVersion, bundleVersion.revision);
+ } catch (BundleException e) {
+ throw new IllegalArgumentException();
+ }
return this;
}
@@ -95,10 +92,8 @@
public TimeZoneBundle buildUnvalidated() throws BundleException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
- if (bundleFormatVersion != null && rulesVersion != null && androidRevision != null) {
- BundleVersion bundleVersion =
- new BundleVersion(bundleFormatVersion, rulesVersion, androidRevision);
- addZipEntry(zos, TimeZoneBundle.BUNDLE_VERSION_FILE_NAME, bundleVersion.getBytes());
+ if (bundleVersion != null) {
+ addZipEntry(zos, TimeZoneBundle.BUNDLE_VERSION_FILE_NAME, bundleVersion.toBytes());
}
if (tzData != null) {
@@ -117,26 +112,9 @@
* Builds a {@link TimeZoneBundle}.
*/
public TimeZoneBundle build() throws BundleException {
- if (bundleFormatVersion == null) {
+ if (bundleVersion == null) {
throw new IllegalStateException("Missing bundleVersion");
}
- if (!BundleVersion.BUNDLE_FORMAT_VERSION_PATTERN.matcher(bundleFormatVersion).matches()) {
- throw new IllegalStateException("bundleVersion invalid: " + bundleFormatVersion);
- }
-
- if (rulesVersion == null) {
- throw new IllegalStateException("Missing rulesVersion");
- }
- if (!BundleVersion.RULES_VERSION_PATTERN.matcher(rulesVersion).matches()) {
- throw new IllegalStateException("rulesVersion invalid: " + rulesVersion);
- }
-
- if (androidRevision == null) {
- throw new IllegalStateException("Missing androidRevision");
- }
- if (!BundleVersion.ANDROID_REVISION_PATTERN.matcher(androidRevision).matches()) {
- throw new IllegalStateException("androidRevision invalid: " + androidRevision);
- }
if (icuData == null) {
throw new IllegalStateException("Missing icuData");
}
diff --git a/tzdata/tools2/testing/prepareTzDataUpdates.sh b/tzdata/tools2/testing/prepareTzDataUpdates.sh
index 99cd60f..b467199 100755
--- a/tzdata/tools2/testing/prepareTzDataUpdates.sh
+++ b/tzdata/tools2/testing/prepareTzDataUpdates.sh
@@ -84,7 +84,7 @@
TZ_PREVIOUS_UPDATE_PROPERTIES=${TMP}/tzupdate.properties.${TZ_PREVIOUS}
cat > ${TZ_PREVIOUS_UPDATE_PROPERTIES} <<EOF
-android.revision=001
+revision=1
rules.version=${TZ_PREVIOUS}
bionic.file=${TMP_PREVIOUS}/tzdata
icu.file=${TMP_PREVIOUS}/icu_tzdata.dat
@@ -113,7 +113,7 @@
TZ_CURRENT_UPDATE_PROPERTIES=${TMP}/tzupdate.properties.${TZ_CURRENT}
cat > ${TZ_CURRENT_UPDATE_PROPERTIES} <<EOF
-android.revision=001
+revision=1
rules.version=${TZ_CURRENT}
bionic.file=${TMP_CURRENT}/tzdata
icu.file=${TMP_CURRENT}/icu_tzdata.dat
@@ -142,7 +142,7 @@
TZ_NEXT_UPDATE_PROPERTIES=${TMP}/tzupdate.properties.${TZ_NEXT}
cat > ${TZ_NEXT_UPDATE_PROPERTIES} <<EOF
-android.revision=001
+revision=1
rules.version=${TZ_NEXT}
bionic.file=${TMP_NEXT}/tzdata
icu.file=${TMP_NEXT}/icu_tzdata.dat
diff --git a/tzdata/tools2/tzupdate.properties b/tzdata/tools2/tzupdate.properties
index f46d942..82fa2c4 100644
--- a/tzdata/tools2/tzupdate.properties
+++ b/tzdata/tools2/tzupdate.properties
@@ -3,8 +3,8 @@
# This should be the tzdata version. e.g. "2015a".
rules.version=
-# This is used to indicate when Android has issued a revision. e.g. "001", "002".
-android.revision=001
+# This is used to indicate when Android has issued a revision. e.g. "1", "2".
+revision=1
bionic.file=
icu.file=
diff --git a/tzdata/update2/src/main/libcore/tzdata/update2/BundleVersion.java b/tzdata/update2/src/main/libcore/tzdata/update2/BundleVersion.java
index 6a366da..1889f18 100644
--- a/tzdata/update2/src/main/libcore/tzdata/update2/BundleVersion.java
+++ b/tzdata/update2/src/main/libcore/tzdata/update2/BundleVersion.java
@@ -17,103 +17,116 @@
package libcore.tzdata.update2;
import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
- * Constants and logic associated with the timezone bundle version file.
+ * Constants and logic associated with the time zone bundle version file.
*/
public class BundleVersion {
/**
- * The current bundle format version in the form XXX.YYY. Increment the first number (XXX)
- * when making incompatible changes to the bundle structure, or the files contained within.
- * The second number (YYY) is currently ignored.
+ * The major bundle format version supported by this device.
+ * Increment this for non-backwards compatible changes to the bundle format.
*/
- public static final String BUNDLE_FORMAT_MAJOR_VERSION = "001";
+ public static final int CURRENT_FORMAT_MAJOR_VERSION = 1;
- public static final String FULL_BUNDLE_FORMAT_VERSION = BUNDLE_FORMAT_MAJOR_VERSION + ".001";
+ /**
+ * The minor bundle format version supported by this device. Increment this for
+ * backwards-compatible changes to the bundle format.
+ */
+ public static final int CURRENT_FORMAT_MINOR_VERSION = 1;
- private static final int BUNDLE_FORMAT_LENGTH = 7;
+ /** The full major + minor bundle format version for this device. */
+ private static final String FULL_CURRENT_FORMAT_VERSION_STRING =
+ toFormatVersionString(CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION);
- public static final Pattern BUNDLE_FORMAT_VERSION_PATTERN = Pattern.compile("\\d{3}\\.\\d{3}");
+ private static final int FORMAT_VERSION_STRING_LENGTH =
+ FULL_CURRENT_FORMAT_VERSION_STRING.length();
+ private static final Pattern FORMAT_VERSION_PATTERN = Pattern.compile("(\\d{3})\\.(\\d{3})");
/** A pattern that matches the IANA rules value of a rules update. e.g. "2016g" */
- public static final Pattern RULES_VERSION_PATTERN = Pattern.compile("\\d{4}\\w");
+ private static final Pattern RULES_VERSION_PATTERN = Pattern.compile("(\\d{4}\\w)");
private static final int RULES_VERSION_LENGTH = 5;
- /** A pattern that matches the Android revision of a rules update. e.g. "001" */
- public static final Pattern ANDROID_REVISION_PATTERN = Pattern.compile("\\d{3}");
+ /** A pattern that matches the revision of a rules update. e.g. "001" */
+ private static final Pattern REVISION_PATTERN = Pattern.compile("(\\d{3})");
- private static final int ANDROID_REVISION_LENGTH = 3;
+ private static final int REVISION_LENGTH = 3;
/**
* The length of a well-formed bundle version file:
- * {Bundle version}|{Rule version}|{Android revision}
+ * {Bundle version}|{Rule version}|{Revision}
*/
- public static final int BUNDLE_VERSION_FILE_LENGTH = BUNDLE_FORMAT_LENGTH + 1
+ static final int BUNDLE_VERSION_FILE_LENGTH = FORMAT_VERSION_STRING_LENGTH + 1
+ RULES_VERSION_LENGTH
- + 1 + ANDROID_REVISION_LENGTH;
+ + 1 + REVISION_LENGTH;
private static final Pattern BUNDLE_VERSION_PATTERN = Pattern.compile(
- BUNDLE_FORMAT_VERSION_PATTERN.pattern() + "\\|"
+ FORMAT_VERSION_PATTERN.pattern() + "\\|"
+ RULES_VERSION_PATTERN.pattern() + "\\|"
- + ANDROID_REVISION_PATTERN.pattern()
+ + REVISION_PATTERN.pattern()
+ ".*" /* ignore trailing */);
- private final String bundleFormatVersion;
-
+ public final int formatMajorVersion;
+ public final int formatMinorVersion;
public final String rulesVersion;
+ public final int revision;
- public final String androidRevision;
-
- public BundleVersion(String bundleFormatVersion, String rulesVersion,
- String androidRevision) throws BundleException {
- if (!BUNDLE_FORMAT_VERSION_PATTERN.matcher(bundleFormatVersion).matches()) {
- throw new BundleException("Invalid bundleFormatVersion: " + bundleFormatVersion);
- }
+ public BundleVersion(int formatMajorVersion, int formatMinorVersion, String rulesVersion,
+ int revision) throws BundleException {
+ this.formatMajorVersion = validate3DigitVersion(formatMajorVersion);
+ this.formatMinorVersion = validate3DigitVersion(formatMinorVersion);
if (!RULES_VERSION_PATTERN.matcher(rulesVersion).matches()) {
throw new BundleException("Invalid rulesVersion: " + rulesVersion);
}
- if (!ANDROID_REVISION_PATTERN.matcher(androidRevision).matches()) {
- throw new BundleException("Invalid androidRevision: " + androidRevision);
- }
- this.bundleFormatVersion = bundleFormatVersion;
this.rulesVersion = rulesVersion;
- this.androidRevision = androidRevision;
+ this.revision = validate3DigitVersion(revision);
}
- public static BundleVersion extractFromBytes(byte[] bytes) throws BundleException {
+ public static BundleVersion fromBytes(byte[] bytes) throws BundleException {
String bundleVersion = new String(bytes, StandardCharsets.US_ASCII);
try {
- if (!BUNDLE_VERSION_PATTERN.matcher(bundleVersion).matches()) {
+ Matcher matcher = BUNDLE_VERSION_PATTERN.matcher(bundleVersion);
+ if (!matcher.matches()) {
throw new BundleException("Invalid bundle version string: " + bundleVersion);
}
- String bundleFormatVersion = bundleVersion.substring(0, 7);
- String rulesVersion = bundleVersion.substring(8, 13);
- String androidRevision = bundleVersion.substring(14);
- return new BundleVersion(bundleFormatVersion, rulesVersion, androidRevision);
+ String formatMajorVersion = matcher.group(1);
+ String formatMinorVersion = matcher.group(2);
+ String rulesVersion = matcher.group(3);
+ String revision = matcher.group(4);
+ return new BundleVersion(
+ from3DigitVersionString(formatMajorVersion),
+ from3DigitVersionString(formatMinorVersion),
+ rulesVersion,
+ from3DigitVersionString(revision));
} catch (IndexOutOfBoundsException e) {
// The use of the regexp above should make this impossible.
throw new BundleException("Bundle version string too short:" + bundleVersion);
}
}
- public String getBundleFormatMajorVersion() {
- return bundleFormatVersion.substring(0, 3);
- }
-
- public byte[] getBytes() {
- return getBytes(bundleFormatVersion, rulesVersion, androidRevision);
+ public byte[] toBytes() {
+ return toBytes(formatMajorVersion, formatMinorVersion, rulesVersion, revision);
}
// @VisibleForTesting - can be used to construct invalid bundle version bytes.
- public static byte[] getBytes(
- String bundleFormatVersion, String rulesVersion, String androidRevision) {
- return (bundleFormatVersion + "|" + rulesVersion + "|" + androidRevision)
+ public static byte[] toBytes(
+ int majorFormatVersion, int minorFormatVerison, String rulesVersion, int revision) {
+ return (toFormatVersionString(majorFormatVersion, minorFormatVerison)
+ + "|" + rulesVersion + "|" + to3DigitVersionString(revision))
.getBytes(StandardCharsets.US_ASCII);
}
+ public static boolean isCompatibleWithThisDevice(BundleVersion bundleVersion) {
+ return (BundleVersion.CURRENT_FORMAT_MAJOR_VERSION
+ == bundleVersion.formatMajorVersion)
+ && (BundleVersion.CURRENT_FORMAT_MINOR_VERSION
+ <= bundleVersion.formatMinorVersion);
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -125,21 +138,65 @@
BundleVersion that = (BundleVersion) o;
- if (!bundleFormatVersion.equals(that.bundleFormatVersion)) {
+ if (formatMajorVersion != that.formatMajorVersion) {
return false;
}
- if (!rulesVersion.equals(that.rulesVersion)) {
+ if (formatMinorVersion != that.formatMinorVersion) {
return false;
}
- return androidRevision.equals(that.androidRevision);
+ if (revision != that.revision) {
+ return false;
+ }
+ return rulesVersion.equals(that.rulesVersion);
}
@Override
public String toString() {
return "BundleVersion{" +
- "bundleFormatVersion='" + bundleFormatVersion + '\'' +
+ "formatMajorVersion=" + formatMajorVersion +
+ ", formatMinorVersion=" + formatMinorVersion +
", rulesVersion='" + rulesVersion + '\'' +
- ", androidRevision='" + androidRevision + '\'' +
+ ", revision=" + revision +
'}';
}
+
+ /**
+ * Returns a version as a zero-padded three-digit String value.
+ */
+ private static String to3DigitVersionString(int version) {
+ try {
+ return String.format(Locale.ROOT, "%03d", validate3DigitVersion(version));
+ } catch (BundleException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Validates and parses a zero-padded three-digit String value.
+ */
+ private static int from3DigitVersionString(String versionString) throws BundleException {
+ final String parseErrorMessage = "versionString must be a zero padded, 3 digit, positive"
+ + " decimal integer";
+ if (versionString.length() != 3) {
+ throw new BundleException(parseErrorMessage);
+ }
+ try {
+ int version = Integer.parseInt(versionString);
+ return validate3DigitVersion(version);
+ } catch (NumberFormatException e) {
+ throw new BundleException(parseErrorMessage, e);
+ }
+ }
+
+ private static int validate3DigitVersion(int value) throws BundleException {
+ if (value < 1 || value > 999) {
+ throw new BundleException("Expected 1 <= value <= 999, was " + value);
+ }
+ return value;
+ }
+
+ private static String toFormatVersionString(int majorFormatVersion, int minorFormatVersion) {
+ return to3DigitVersionString(majorFormatVersion)
+ + "." + to3DigitVersionString(minorFormatVersion);
+ }
}
diff --git a/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundle.java b/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundle.java
index 6d11469..f517b5a 100644
--- a/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundle.java
+++ b/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundle.java
@@ -26,7 +26,7 @@
import java.util.zip.ZipInputStream;
/**
- * A timezone bundle. This is a thin wrapper around some in-memory bytes representing a zip
+ * A time zone bundle. This is a thin wrapper around some in-memory bytes representing a zip
* archive and logic for its safe extraction.
*/
public final class TimeZoneBundle {
@@ -67,7 +67,7 @@
if (contents == null) {
throw new BundleException("Bundle version file entry not found");
}
- return BundleVersion.extractFromBytes(contents);
+ return BundleVersion.fromBytes(contents);
}
private static byte[] getEntryContents(InputStream is, String entryName) throws IOException {
diff --git a/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundleInstaller.java b/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundleInstaller.java
index 601b8e2..c2ad47e 100644
--- a/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundleInstaller.java
+++ b/tzdata/update2/src/main/libcore/tzdata/update2/TimeZoneBundleInstaller.java
@@ -27,6 +27,16 @@
* testing. This class is not thread-safe: callers are expected to handle mutual exclusion.
*/
public final class TimeZoneBundleInstaller {
+ /** {@link #installWithErrorCode(byte[])} result code: Success. */
+ public final static int INSTALL_SUCCESS = 0;
+ /** {@link #installWithErrorCode(byte[])} result code: Bundle corrupt. */
+ public final static int INSTALL_FAIL_BAD_BUNDLE_STRUCTURE = 1;
+ /** {@link #installWithErrorCode(byte[])} result code: Bundle version incompatible. */
+ public final static int INSTALL_FAIL_BAD_BUNDLE_FORMAT_VERSION = 2;
+ /** {@link #installWithErrorCode(byte[])} result code: Bundle rules too old for device. */
+ public final static int INSTALL_FAIL_RULES_TOO_OLD = 3;
+ /** {@link #installWithErrorCode(byte[])} result code: Bundle content failed validation. */
+ public final static int INSTALL_FAIL_VALIDATION_ERROR = 4;
private static final String CURRENT_TZ_DATA_DIR_NAME = "current";
private static final String WORKING_DIR_NAME = "working";
@@ -69,6 +79,17 @@
* If the installation completed successfully this method returns {@code true}.
*/
public boolean install(byte[] content) throws IOException {
+ int result = installWithErrorCode(content);
+ return result == INSTALL_SUCCESS;
+ }
+
+ /**
+ * Install the supplied time zone bundle.
+ *
+ * <p>Errors during unpacking or installation will throw an {@link IOException}.
+ * Returns {@link #INSTALL_SUCCESS} or an error code.
+ */
+ public int installWithErrorCode(byte[] content) throws IOException {
if (oldTzDataDir.exists()) {
FileUtils.deleteRecursive(oldTzDataDir);
}
@@ -84,39 +105,39 @@
bundleVersion = readBundleVersion(workingDir);
} catch (BundleException e) {
Slog.i(logTag, "Invalid bundle version: " + e.getMessage());
- return false;
+ return INSTALL_FAIL_BAD_BUNDLE_STRUCTURE;
}
if (bundleVersion == null) {
Slog.i(logTag, "Update not applied: Bundle version could not be loaded");
- return false;
+ return INSTALL_FAIL_BAD_BUNDLE_STRUCTURE;
}
- if (!checkBundleFormatVersion(bundleVersion)) {
+ if (!BundleVersion.isCompatibleWithThisDevice(bundleVersion)) {
Slog.i(logTag, "Update not applied: Bundle format version check failed: "
+ bundleVersion);
- return false;
+ return INSTALL_FAIL_BAD_BUNDLE_FORMAT_VERSION;
}
if (!checkBundleDataFilesExist(workingDir)) {
Slog.i(logTag, "Update not applied: Bundle is missing required data file(s)");
- return false;
+ return INSTALL_FAIL_BAD_BUNDLE_STRUCTURE;
}
if (!checkBundleRulesNewerThanSystem(systemTzDataFile, bundleVersion)) {
Slog.i(logTag, "Update not applied: Bundle rules version check failed");
- return false;
+ return INSTALL_FAIL_RULES_TOO_OLD;
}
File zoneInfoFile = new File(workingDir, TimeZoneBundle.TZDATA_FILE_NAME);
ZoneInfoDB.TzData tzData = ZoneInfoDB.TzData.loadTzData(zoneInfoFile.getPath());
if (tzData == null) {
Slog.i(logTag, "Update not applied: " + zoneInfoFile + " could not be loaded");
- return false;
+ return INSTALL_FAIL_VALIDATION_ERROR;
}
try {
tzData.validate();
} catch (IOException e) {
Slog.i(logTag, "Update not applied: " + zoneInfoFile + " failed validation", e);
- return false;
+ return INSTALL_FAIL_VALIDATION_ERROR;
} finally {
tzData.close();
}
@@ -133,7 +154,7 @@
Slog.i(logTag, "Moving " + workingDir + " to " + currentTzDataDir);
FileUtils.rename(workingDir, currentTzDataDir);
Slog.i(logTag, "Update applied: " + currentTzDataDir + " successfully created");
- return true;
+ return INSTALL_SUCCESS;
} finally {
deleteBestEffort(oldTzDataDir);
deleteBestEffort(workingDir);
@@ -161,16 +182,17 @@
return false;
}
- try {
- Slog.i(logTag, "Moving " + currentTzDataDir + " to " + oldTzDataDir);
- // Move currentTzDataDir out of the way in one operation so we can't partially delete
- // the contents, which would leave a partial install.
- FileUtils.rename(currentTzDataDir, oldTzDataDir);
- return true;
- } finally {
- // Do our best to delete the now uninstalled timezone data.
- deleteBestEffort(oldTzDataDir);
- }
+ Slog.i(logTag, "Moving " + currentTzDataDir + " to " + oldTzDataDir);
+ // Move currentTzDataDir out of the way in one operation so we can't partially delete
+ // the contents, which would leave a partial install.
+ FileUtils.rename(currentTzDataDir, oldTzDataDir);
+
+ // Do our best to delete the now uninstalled timezone data.
+ deleteBestEffort(oldTzDataDir);
+
+ Slog.i(logTag, "Time zone update uninstalled.");
+
+ return true;
}
/**
@@ -199,6 +221,7 @@
private void deleteBestEffort(File dir) {
if (dir.exists()) {
+ Slog.i(logTag, "Deleting " + dir);
try {
FileUtils.deleteRecursive(dir);
} catch (IOException e) {
@@ -230,12 +253,7 @@
}
byte[] versionBytes =
FileUtils.readBytes(bundleVersionFile, BundleVersion.BUNDLE_VERSION_FILE_LENGTH);
- return BundleVersion.extractFromBytes(versionBytes);
- }
-
- private boolean checkBundleFormatVersion(BundleVersion bundleVersion) {
- return bundleVersion.getBundleFormatMajorVersion()
- .equals(BundleVersion.BUNDLE_FORMAT_MAJOR_VERSION);
+ return BundleVersion.fromBytes(versionBytes);
}
/**
diff --git a/tzdata/update2/src/test/libcore/tzdata/update2/BundleVersionTest.java b/tzdata/update2/src/test/libcore/tzdata/update2/BundleVersionTest.java
new file mode 100644
index 0000000..3c2bff8
--- /dev/null
+++ b/tzdata/update2/src/test/libcore/tzdata/update2/BundleVersionTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package libcore.tzdata.update2;
+
+import junit.framework.TestCase;
+
+public class BundleVersionTest extends TestCase {
+
+ private static final int INVALID_VERSION_LOW = 0;
+ private static final int VALID_VERSION = 23;
+ private static final int INVALID_VERSION_HIGH = 1000;
+ private static final String VALID_RULES_VERSION = "2016a";
+ private static final String INVALID_RULES_VERSION = "A016a";
+
+ public void testConstructorValidation() throws Exception {
+ checkConstructorThrows(
+ INVALID_VERSION_LOW, VALID_VERSION, VALID_RULES_VERSION, VALID_VERSION);
+ checkConstructorThrows(
+ INVALID_VERSION_HIGH, VALID_VERSION, VALID_RULES_VERSION, VALID_VERSION);
+ checkConstructorThrows(
+ VALID_VERSION, INVALID_VERSION_LOW, VALID_RULES_VERSION, VALID_VERSION);
+ checkConstructorThrows(
+ VALID_VERSION, INVALID_VERSION_HIGH, VALID_RULES_VERSION, VALID_VERSION);
+ checkConstructorThrows(VALID_VERSION, VALID_VERSION, INVALID_RULES_VERSION, VALID_VERSION);
+ checkConstructorThrows(VALID_VERSION, VALID_VERSION, VALID_RULES_VERSION,
+ INVALID_VERSION_LOW);
+ checkConstructorThrows(VALID_VERSION, VALID_VERSION, VALID_RULES_VERSION,
+ INVALID_VERSION_HIGH);
+ }
+
+ private static void checkConstructorThrows(
+ int majorVersion, int minorVersion, String rulesVersion, int revision) {
+ try {
+ new BundleVersion(majorVersion, minorVersion, rulesVersion, revision);
+ fail();
+ } catch (BundleException expected) {}
+ }
+
+ public void testConstructor() throws Exception {
+ BundleVersion bundleVersion = new BundleVersion(1, 2, VALID_RULES_VERSION, 3);
+ assertEquals(1, bundleVersion.formatMajorVersion);
+ assertEquals(2, bundleVersion.formatMinorVersion);
+ assertEquals(VALID_RULES_VERSION, bundleVersion.rulesVersion);
+ assertEquals(3, bundleVersion.revision);
+ }
+
+ public void testToFromBytesRoundTrip() throws Exception {
+ BundleVersion bundleVersion = new BundleVersion(1, 2, VALID_RULES_VERSION, 3);
+ assertEquals(bundleVersion, BundleVersion.fromBytes(bundleVersion.toBytes()));
+ }
+
+ public void testIsCompatibleWithThisDevice() throws Exception {
+ BundleVersion exactMatch = createBundleVersion(
+ BundleVersion.CURRENT_FORMAT_MAJOR_VERSION,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION);
+ assertTrue(BundleVersion.isCompatibleWithThisDevice(exactMatch));
+
+ BundleVersion newerMajor = createBundleVersion(
+ BundleVersion.CURRENT_FORMAT_MAJOR_VERSION + 1,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION);
+ assertFalse(BundleVersion.isCompatibleWithThisDevice(newerMajor));
+
+ BundleVersion newerMinor = createBundleVersion(
+ BundleVersion.CURRENT_FORMAT_MAJOR_VERSION,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION + 1);
+ assertTrue(BundleVersion.isCompatibleWithThisDevice(newerMinor));
+
+ if (BundleVersion.CURRENT_FORMAT_MAJOR_VERSION > 1) {
+ BundleVersion olderMajor = createBundleVersion(
+ BundleVersion.CURRENT_FORMAT_MAJOR_VERSION - 1,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION);
+ assertFalse(BundleVersion.isCompatibleWithThisDevice(olderMajor));
+ }
+
+ if (BundleVersion.CURRENT_FORMAT_MINOR_VERSION > 1) {
+ BundleVersion olderMinor = createBundleVersion(
+ BundleVersion.CURRENT_FORMAT_MAJOR_VERSION,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION - 1);
+ assertFalse(BundleVersion.isCompatibleWithThisDevice(olderMinor));
+ }
+ }
+
+ private BundleVersion createBundleVersion(int majorFormatVersion, int minorFormatVersion)
+ throws BundleException {
+ return new BundleVersion(majorFormatVersion, minorFormatVersion, VALID_RULES_VERSION, 3);
+ }
+}
diff --git a/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleInstallerTest.java b/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleInstallerTest.java
index 0c7e52b..fc8fa92 100644
--- a/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleInstallerTest.java
+++ b/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleInstallerTest.java
@@ -91,10 +91,10 @@
File doesNotExist = new File(testSystemTzDataDir, "doesNotExist");
TimeZoneBundleInstaller brokenSystemInstaller = new TimeZoneBundleInstaller(
"TimeZoneBundleInstallerTest", doesNotExist, testInstallDir);
- TimeZoneBundle tzData = createValidTimeZoneBundle(NEW_RULES_VERSION, "001");
+ TimeZoneBundle tzData = createValidTimeZoneBundle(NEW_RULES_VERSION, 1);
try {
- brokenSystemInstaller.install(tzData.getBytes());
+ brokenSystemInstaller.installWithErrorCode(tzData.getBytes());
fail();
} catch (IOException expected) {}
@@ -103,9 +103,11 @@
/** Tests the first successful update on a device */
public void testInstall_successfulFirstUpdate() throws Exception {
- TimeZoneBundle bundle = createValidTimeZoneBundle(NEW_RULES_VERSION, "001");
+ TimeZoneBundle bundle = createValidTimeZoneBundle(NEW_RULES_VERSION, 1);
- assertTrue(installer.install(bundle.getBytes()));
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(bundle.getBytes()));
assertBundleInstalled(bundle);
}
@@ -113,8 +115,10 @@
* Tests we can install an update the same version as is in /system.
*/
public void testInstall_successfulFirstUpdate_sameVersionAsSystem() throws Exception {
- TimeZoneBundle bundle = createValidTimeZoneBundle(SYSTEM_RULES_VERSION, "001");
- assertTrue(installer.install(bundle.getBytes()));
+ TimeZoneBundle bundle = createValidTimeZoneBundle(SYSTEM_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(bundle.getBytes()));
assertBundleInstalled(bundle);
}
@@ -122,8 +126,10 @@
* Tests we cannot install an update older than the version in /system.
*/
public void testInstall_unsuccessfulFirstUpdate_olderVersionThanSystem() throws Exception {
- TimeZoneBundle bundle = createValidTimeZoneBundle(OLDER_RULES_VERSION, "001");
- assertFalse(installer.install(bundle.getBytes()));
+ TimeZoneBundle bundle = createValidTimeZoneBundle(OLDER_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_RULES_TOO_OLD,
+ installer.installWithErrorCode(bundle.getBytes()));
assertNoContentInstalled();
}
@@ -131,16 +137,22 @@
* Tests an update on a device when there is a prior update already applied.
*/
public void testInstall_successfulFollowOnUpdate_newerVersion() throws Exception {
- TimeZoneBundle bundle1 = createValidTimeZoneBundle(NEW_RULES_VERSION, "001");
- assertTrue(installer.install(bundle1.getBytes()));
+ TimeZoneBundle bundle1 = createValidTimeZoneBundle(NEW_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(bundle1.getBytes()));
assertBundleInstalled(bundle1);
- TimeZoneBundle bundle2 = createValidTimeZoneBundle(NEW_RULES_VERSION, "002");
- assertTrue(installer.install(bundle2.getBytes()));
+ TimeZoneBundle bundle2 = createValidTimeZoneBundle(NEW_RULES_VERSION, 2);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(bundle2.getBytes()));
assertBundleInstalled(bundle2);
- TimeZoneBundle bundle3 = createValidTimeZoneBundle(NEWER_RULES_VERSION, "001");
- assertTrue(installer.install(bundle3.getBytes()));
+ TimeZoneBundle bundle3 = createValidTimeZoneBundle(NEWER_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(bundle3.getBytes()));
assertBundleInstalled(bundle3);
}
@@ -149,40 +161,52 @@
* on update is older than in /system.
*/
public void testInstall_unsuccessfulFollowOnUpdate_olderVersion() throws Exception {
- TimeZoneBundle bundle1 = createValidTimeZoneBundle(NEW_RULES_VERSION, "002");
- assertTrue(installer.install(bundle1.getBytes()));
+ TimeZoneBundle bundle1 = createValidTimeZoneBundle(NEW_RULES_VERSION, 2);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(bundle1.getBytes()));
assertBundleInstalled(bundle1);
- TimeZoneBundle bundle2 = createValidTimeZoneBundle(OLDER_RULES_VERSION, "001");
- assertFalse(installer.install(bundle2.getBytes()));
+ TimeZoneBundle bundle2 = createValidTimeZoneBundle(OLDER_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_RULES_TOO_OLD,
+ installer.installWithErrorCode(bundle2.getBytes()));
assertBundleInstalled(bundle1);
}
/** Tests that a bundle with a missing file will not update the content. */
public void testInstall_missingTzDataFile() throws Exception {
- TimeZoneBundle installedBundle = createValidTimeZoneBundle(NEW_RULES_VERSION, "001");
- assertTrue(installer.install(installedBundle.getBytes()));
+ TimeZoneBundle installedBundle = createValidTimeZoneBundle(NEW_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(installedBundle.getBytes()));
assertBundleInstalled(installedBundle);
TimeZoneBundle incompleteBundle =
- createValidTimeZoneBundleBuilder(NEWER_RULES_VERSION, "001")
+ createValidTimeZoneBundleBuilder(NEWER_RULES_VERSION, 1)
.clearTzDataForTests()
.buildUnvalidated();
- assertFalse(installer.install(incompleteBundle.getBytes()));
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_BAD_BUNDLE_STRUCTURE,
+ installer.installWithErrorCode(incompleteBundle.getBytes()));
assertBundleInstalled(installedBundle);
}
/** Tests that a bundle with a missing file will not update the content. */
public void testInstall_missingIcuFile() throws Exception {
- TimeZoneBundle installedBundle = createValidTimeZoneBundle(NEW_RULES_VERSION, "001");
- assertTrue(installer.install(installedBundle.getBytes()));
+ TimeZoneBundle installedBundle = createValidTimeZoneBundle(NEW_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(installedBundle.getBytes()));
assertBundleInstalled(installedBundle);
TimeZoneBundle incompleteBundle =
- createValidTimeZoneBundleBuilder(NEWER_RULES_VERSION, "001")
+ createValidTimeZoneBundleBuilder(NEWER_RULES_VERSION, 1)
.clearIcuDataForTests()
.buildUnvalidated();
- assertFalse(installer.install(incompleteBundle.getBytes()));
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_BAD_BUNDLE_STRUCTURE,
+ installer.installWithErrorCode(incompleteBundle.getBytes()));
assertBundleInstalled(installedBundle);
}
@@ -194,8 +218,10 @@
assertTrue(workingDir.mkdir());
createFile(new File(workingDir, "myFile"), new byte[] { 'a' });
- TimeZoneBundle bundle = createValidTimeZoneBundle(NEW_RULES_VERSION, "001");
- assertTrue(installer.install(bundle.getBytes()));
+ TimeZoneBundle bundle = createValidTimeZoneBundle(NEW_RULES_VERSION, 1);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_SUCCESS,
+ installer.installWithErrorCode(bundle.getBytes()));
assertBundleInstalled(bundle);
}
@@ -204,10 +230,12 @@
*/
public void testInstall_withMissingBundleVersionFile() throws Exception {
// Create a bundle without a version file.
- TimeZoneBundle bundle = createValidTimeZoneBundleBuilder(NEW_RULES_VERSION, "001")
+ TimeZoneBundle bundle = createValidTimeZoneBundleBuilder(NEW_RULES_VERSION, 1)
.clearVersionForTests()
.buildUnvalidated();
- assertFalse(installer.install(bundle.getBytes()));
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_BAD_BUNDLE_STRUCTURE,
+ installer.installWithErrorCode(bundle.getBytes()));
assertNoContentInstalled();
}
@@ -216,10 +244,12 @@
*/
public void testInstall_withNewerBundleVersion() throws Exception {
// Create a bundle that will appear to be newer than the one currently supported.
- TimeZoneBundle bundle = createValidTimeZoneBundleBuilder(NEW_RULES_VERSION, "001")
- .setBundleVersionForTests("002.001")
+ TimeZoneBundle bundle = createValidTimeZoneBundleBuilder(NEW_RULES_VERSION, 1)
+ .replaceFormatVersionForTests(2, 1)
.buildUnvalidated();
- assertFalse(installer.install(bundle.getBytes()));
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_BAD_BUNDLE_FORMAT_VERSION,
+ installer.installWithErrorCode(bundle.getBytes()));
assertNoContentInstalled();
}
@@ -229,37 +259,46 @@
public void testInstall_withBadlyFormedBundleVersion() throws Exception {
// Create a bundle that has an invalid major bundle version. It should be 3 numeric
// characters, "." and 3 more numeric characters.
- String invalidBundleVersion = "A01.001";
- byte[] versionBytes =
- BundleVersion.getBytes(invalidBundleVersion, NEW_RULES_VERSION, "001");
- TimeZoneBundle bundle = createTimeZoneBundleWithVersionBytes(versionBytes);
- assertFalse(installer.install(bundle.getBytes()));
+ BundleVersion validBundleVersion = new BundleVersion(1, 1, NEW_RULES_VERSION, 1);
+ byte[] invalidFormatVersionBytes = validBundleVersion.toBytes();
+ invalidFormatVersionBytes[0] = 'A';
+
+ TimeZoneBundle bundle = createTimeZoneBundleWithVersionBytes(invalidFormatVersionBytes);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_BAD_BUNDLE_STRUCTURE,
+ installer.installWithErrorCode(bundle.getBytes()));
assertNoContentInstalled();
}
/**
- * Tests that a bundle with a badly formed android revision will be rejected.
+ * Tests that a bundle with a badly formed revision will be rejected.
*/
- public void testInstall_withBadlyFormedAndroidRevision() throws Exception {
- // Create a bundle that has an invalid Android revision. It should be 3 numeric characters.
- String invalidAndroidRevision = "A01";
- byte[] versionBytes = BundleVersion.getBytes(BundleVersion.FULL_BUNDLE_FORMAT_VERSION,
- NEW_RULES_VERSION, invalidAndroidRevision);
- TimeZoneBundle bundle = createTimeZoneBundleWithVersionBytes(versionBytes);
- assertFalse(installer.install(bundle.getBytes()));
+ public void testInstall_withBadlyFormedRevision() throws Exception {
+ // Create a bundle that has an invalid revision. It should be 3 numeric characters.
+ BundleVersion validBundleVersion = new BundleVersion(1, 1, NEW_RULES_VERSION, 1);
+ byte[] invalidRevisionBytes = validBundleVersion.toBytes();
+ invalidRevisionBytes[invalidRevisionBytes.length - 3] = 'A';
+
+ TimeZoneBundle bundle = createTimeZoneBundleWithVersionBytes(invalidRevisionBytes);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_BAD_BUNDLE_STRUCTURE,
+ installer.installWithErrorCode(bundle.getBytes()));
assertNoContentInstalled();
}
/**
- * Tests that a bundle with a badly formed android revision will be rejected.
+ * Tests that a bundle with a badly formed rules version will be rejected.
*/
public void testInstall_withBadlyFormedRulesVersion() throws Exception {
// Create a bundle that has an invalid rules version. It should be in the form "2016c".
- final String invalidRulesVersion = "203Bc";
- byte[] versionBytes = BundleVersion.getBytes(BundleVersion.FULL_BUNDLE_FORMAT_VERSION,
- invalidRulesVersion, "001");
- TimeZoneBundle bundle = createTimeZoneBundleWithVersionBytes(versionBytes);
- assertFalse(installer.install(bundle.getBytes()));
+ BundleVersion validBundleVersion = new BundleVersion(1, 1, NEW_RULES_VERSION, 1);
+ byte[] invalidRulesVersionBytes = validBundleVersion.toBytes();
+ invalidRulesVersionBytes[invalidRulesVersionBytes.length - 6] = 'B';
+
+ TimeZoneBundle bundle = createTimeZoneBundleWithVersionBytes(invalidRulesVersionBytes);
+ assertEquals(
+ TimeZoneBundleInstaller.INSTALL_FAIL_BAD_BUNDLE_STRUCTURE,
+ installer.installWithErrorCode(bundle.getBytes()));
assertNoContentInstalled();
}
@@ -292,19 +331,22 @@
}
private static TimeZoneBundle createValidTimeZoneBundle(
- String rulesVersion, String androidRevision) throws Exception {
- return createValidTimeZoneBundleBuilder(rulesVersion, androidRevision).build();
+ String rulesVersion, int revision) throws Exception {
+ return createValidTimeZoneBundleBuilder(rulesVersion, revision).build();
}
private static TimeZoneBundleBuilder createValidTimeZoneBundleBuilder(
- String rulesVersion, String androidRevision) throws Exception {
+ String rulesVersion, int revision) throws Exception {
byte[] bionicTzData = createTzData(rulesVersion);
byte[] icuData = new byte[] { 'a' };
-
+ BundleVersion bundleVersion = new BundleVersion(
+ BundleVersion.CURRENT_FORMAT_MAJOR_VERSION,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION,
+ rulesVersion,
+ revision);
return new TimeZoneBundleBuilder()
- .setRulesVersion(rulesVersion)
- .setAndroidRevision(androidRevision)
+ .setBundleVersion(bundleVersion)
.setTzData(bionicTzData)
.setIcuData(icuData);
}
@@ -396,7 +438,7 @@
throws Exception {
// Create a valid bundle, then manipulate the version file.
- TimeZoneBundle bundle = createValidTimeZoneBundle(NEW_RULES_VERSION, "001");
+ TimeZoneBundle bundle = createValidTimeZoneBundle(NEW_RULES_VERSION, 1);
byte[] bundleBytes = bundle.getBytes();
ByteArrayOutputStream baos = new ByteArrayOutputStream(bundleBytes.length);
diff --git a/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleTest.java b/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleTest.java
index 6aaf199..0e0b13b 100644
--- a/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleTest.java
+++ b/tzdata/update2/src/test/libcore/tzdata/update2/TimeZoneBundleTest.java
@@ -49,12 +49,12 @@
}
public void testGetBundleVersion() throws Exception {
- BundleVersion bundleVersion =
- new BundleVersion(BundleVersion.FULL_BUNDLE_FORMAT_VERSION, "2016c", "001");
+ BundleVersion bundleVersion = new BundleVersion(BundleVersion.CURRENT_FORMAT_MAJOR_VERSION,
+ BundleVersion.CURRENT_FORMAT_MINOR_VERSION, "2016c", 1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zipOutputStream = new ZipOutputStream(baos)) {
addZipEntry(zipOutputStream, TimeZoneBundle.BUNDLE_VERSION_FILE_NAME,
- bundleVersion.getBytes());
+ bundleVersion.toBytes());
}
TimeZoneBundle bundle = new TimeZoneBundle(baos.toByteArray());