am 08855205: am 77a7e48a: Fix a bug in DefaultHostnameVerifier wildcard handling.
* commit '0885520573d05fc656043713326879abf072b803':
Fix a bug in DefaultHostnameVerifier wildcard handling.
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1618f1b..7298eb0 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -45,6 +45,9 @@
#$(call add-clean-step, find $(OUT) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
#$(call add-clean-step, rm -rf $(OUT)/obj/SHARED_LIBRARIES/libdvm*)
+$(call add-clean-step, rm -rf $(OUT)/system/framework/conscrypt-nojarjar.jar)
+$(call add-clean-step, rm -rf $(OUT)/system/framework/conscrypt-nojarjar.jar)
+$(call add-clean-step, rm -rf $(OUT)/system/etc/security/cacerts/*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 673c0bf..f4cde58 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -50,18 +50,20 @@
endef
# The Java files and their associated resources.
-core_src_files := $(call all-main-java-files-under,dalvik dex dom json luni support xml)
-core_src_files += $(call all-main-java-files-under,libdvm)
+common_core_src_files := $(call all-main-java-files-under,dalvik dex dom json luni xml)
core_resource_dirs := $(call all-core-resource-dirs,main)
test_resource_dirs := $(call all-core-resource-dirs,test)
ifeq ($(EMMA_INSTRUMENT),true)
ifneq ($(EMMA_INSTRUMENT_STATIC),true)
- core_src_files += $(call all-java-files-under, ../external/emma/core ../external/emma/pregenerated)
+ common_core_src_files += $(call all-java-files-under, ../external/emma/core ../external/emma/pregenerated)
core_resource_dirs += ../external/emma/core/res ../external/emma/pregenerated/res
endif
endif
+libdvm_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libdvm)
+libart_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libart)
+
local_javac_flags=-encoding UTF-8
#local_javac_flags+=-Xlint:all -Xlint:-serial,-deprecation,-unchecked
local_javac_flags+=-Xmaxwarns 9999999
@@ -73,23 +75,28 @@
# Definitions to make the core library.
include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(core_src_files)
+LOCAL_SRC_FILES := $(libdvm_core_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
-
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_DX_FLAGS := --core-library
-
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := core
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
LOCAL_REQUIRED_MODULES := tzdata
-
include $(BUILD_JAVA_LIBRARY)
-core-intermediates := ${intermediates}
-
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(libart_core_src_files)
+LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_DX_FLAGS := --core-library
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := core-libart
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+LOCAL_REQUIRED_MODULES := tzdata
+include $(BUILD_JAVA_LIBRARY)
# Create the conscrypt library
include $(CLEAR_VARS)
@@ -100,6 +107,7 @@
LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := conscrypt
+LOCAL_REQUIRED_MODULES := libjavacrypto
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
include $(BUILD_JAVA_LIBRARY)
@@ -112,24 +120,53 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := conscrypt-nojarjar
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
-include $(BUILD_JAVA_LIBRARY)
+include $(BUILD_STATIC_JAVA_LIBRARY)
ifeq ($(LIBCORE_SKIP_TESTS),)
# Make the core-tests library.
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-test-java-files-under,crypto dalvik dom harmony-tests json luni support xml)
+LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom harmony-tests json luni xml)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core conscrypt-nojarjar core-junit okhttp
-LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc mockwebserver nist-pkix-tests okhttp-tests
+LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit okhttp
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests okhttp-tests
LOCAL_JAVACFLAGS := $(local_javac_flags)
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
LOCAL_MODULE := core-tests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
include $(BUILD_STATIC_JAVA_LIBRARY)
endif
+ifeq ($(LIBCORE_SKIP_TESTS),)
+# Make the core-tests-support library.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
+LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_MODULE := core-tests-support
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+include $(BUILD_STATIC_JAVA_LIBRARY)
+endif
+
+ifeq ($(LIBCORE_SKIP_TESTS),)
+# Make the conscrypt-tests library.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-test-java-files-under,crypto)
+LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support conscrypt-nojarjar
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := conscrypt-tests
+LOCAL_REQUIRED_MODULES := libjavacrypto
+LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+include $(BUILD_STATIC_JAVA_LIBRARY)
+endif
+
# This one's tricky. One of our tests needs to have a
# resource with a "#" in its name, but Perforce doesn't
# allow us to submit such a file. So we create it here
@@ -158,23 +195,30 @@
ifeq ($(WITH_HOST_DALVIK),true)
# Definitions to make the core library.
-
include $(CLEAR_VARS)
-
- LOCAL_SRC_FILES := $(core_src_files)
+ LOCAL_SRC_FILES := $(libdvm_core_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
-
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_DX_FLAGS := --core-library
-
LOCAL_BUILD_HOST_DEX := true
-
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := core-hostdex
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
LOCAL_REQUIRED_MODULES := tzdata-host
+ include $(BUILD_HOST_JAVA_LIBRARY)
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := $(libart_core_src_files)
+ LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
+ LOCAL_NO_STANDARD_LIBRARIES := true
+ LOCAL_JAVACFLAGS := $(local_javac_flags)
+ LOCAL_DX_FLAGS := --core-library
+ LOCAL_BUILD_HOST_DEX := true
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE := core-libart-hostdex
+ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+ LOCAL_REQUIRED_MODULES := tzdata-host
include $(BUILD_HOST_JAVA_LIBRARY)
# Make the conscrypt-hostdex library
@@ -187,6 +231,7 @@
LOCAL_BUILD_HOST_DEX := true
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := conscrypt-hostdex
+ LOCAL_REQUIRED_MODULES := libjavacrypto
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
include $(BUILD_HOST_JAVA_LIBRARY)
@@ -205,19 +250,49 @@
# Make the core-tests library.
ifeq ($(LIBCORE_SKIP_TESTS),)
include $(CLEAR_VARS)
- LOCAL_SRC_FILES := $(call all-test-java-files-under,crypto dalvik dom json luni support xml)
+ LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom json luni xml)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
- LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex conscrypt-hostdex-nojarjar core-junit-hostdex okhttp-hostdex
+ LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex core-junit-hostdex core-tests-support-hostdex okhttp-hostdex
LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
LOCAL_JAVACFLAGS := $(local_javac_flags)
- LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := core-tests-hostdex
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
LOCAL_BUILD_HOST_DEX := true
include $(BUILD_HOST_JAVA_LIBRARY)
endif
+
+ # Make the core-tests-support library.
+ ifeq ($(LIBCORE_SKIP_TESTS),)
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
+ LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
+ LOCAL_NO_STANDARD_LIBRARIES := true
+ LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex core-junit-hostdex
+ LOCAL_JAVACFLAGS := $(local_javac_flags)
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE := core-tests-support-hostdex
+ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+ LOCAL_BUILD_HOST_DEX := true
+ include $(BUILD_HOST_JAVA_LIBRARY)
+ endif
+
+ # Make the conscrypt-tests library.
+ ifeq ($(LIBCORE_SKIP_TESTS),)
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := $(call all-test-java-files-under,crypto)
+ LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
+ LOCAL_NO_STANDARD_LIBRARIES := true
+ LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex core-junit-hostdex core-tests-support-hostdex conscrypt-hostdex-nojarjar
+ LOCAL_JAVACFLAGS := $(local_javac_flags)
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE := conscrypt-tests-hostdex
+ LOCAL_REQUIRED_MODULES := libjavacrypto
+ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+ LOCAL_BUILD_HOST_DEX := true
+ include $(BUILD_HOST_JAVA_LIBRARY)
+ endif
endif
#
diff --git a/NativeCode.mk b/NativeCode.mk
index 3a22575..1a47ee4 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -59,7 +59,7 @@
# Include the sub.mk files.
$(foreach dir, \
- crypto/src/main/native dalvik/src/main/native luni/src/main/native, \
+ dalvik/src/main/native luni/src/main/native, \
$(eval $(call include-core-native-dir,$(dir))))
# Extract out the allowed LOCAL_* variables.
@@ -67,7 +67,7 @@
core_shared_libraries := $(LOCAL_SHARED_LIBRARIES)
core_static_libraries := $(LOCAL_STATIC_LIBRARIES)
core_cflags := -Wall -Wextra -Werror
-core_cflags += -DJNI_JARJAR_PREFIX="com/android/"
+core_cppflags += -std=gnu++11
core_test_files := \
luni/src/test/native/test_openssl_engine.cpp \
@@ -81,7 +81,7 @@
LOCAL_CPPFLAGS += $(core_cppflags)
LOCAL_SRC_FILES += $(core_src_files)
LOCAL_C_INCLUDES += $(core_c_includes)
-LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat libicuuc libicui18n libssl libcrypto libz libnativehelper
+LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libcrypto libexpat libicuuc libicui18n libnativehelper libz
LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacore
@@ -89,6 +89,22 @@
include external/stlport/libstlport.mk
include $(BUILD_SHARED_LIBRARY)
+# Platform conscrypt crypto library
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += $(core_cflags)
+LOCAL_CFLAGS += -DJNI_JARJAR_PREFIX="com/android/"
+LOCAL_CPPFLAGS += $(core_cppflags)
+LOCAL_SRC_FILES := \
+ crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
+LOCAL_C_INCLUDES += $(core_c_includes) \
+ libcore/luni/src/main/native
+LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libcrypto libssl libnativehelper libz libjavacore
+LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libjavacrypto
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
+include external/stlport/libstlport.mk
+include $(BUILD_SHARED_LIBRARY)
# Test JNI library.
ifeq ($(LIBCORE_SKIP_TESTS),)
@@ -122,22 +138,38 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacore
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
- LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat-host libicuuc-host libicui18n-host libssl-host libcrypto-host libz-host
+ LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat-host libicuuc-host libicui18n-host libcrypto-host libz-host
+ LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
+ include $(BUILD_HOST_SHARED_LIBRARY)
+
+ # Conscrypt native library for host
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES += \
+ crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
+ LOCAL_C_INCLUDES += $(core_c_includes) \
+ libcore/luni/src/main/native
+ LOCAL_CPPFLAGS += $(core_cppflags)
+ LOCAL_LDLIBS += -lpthread
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE := libjavacrypto
+ LOCAL_CFLAGS += -DJNI_JARJAR_PREFIX="com/android/"
+ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
+ LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libssl-host libcrypto-host libjavacore
LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
include $(BUILD_HOST_SHARED_LIBRARY)
# Conscrypt native library for nojarjar'd version
include $(CLEAR_VARS)
LOCAL_SRC_FILES += \
- crypto/src/main/native/org_conscrypt_NativeCrypto.cpp \
- luni/src/main/native/AsynchronousSocketCloseMonitor.cpp
- LOCAL_C_INCLUDES += $(core_c_includes)
+ crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
+ LOCAL_C_INCLUDES += $(core_c_includes) \
+ libcore/luni/src/main/native
LOCAL_CPPFLAGS += $(core_cppflags)
LOCAL_LDLIBS += -lpthread
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libconscrypt_jni
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
- LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libssl-host libcrypto-host
+ LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libssl-host libcrypto-host libjavacore
LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/benchmarks/src/benchmarks/regression/CharsetBenchmark.java b/benchmarks/src/benchmarks/regression/CharsetBenchmark.java
index 6ecada7..21b9966 100644
--- a/benchmarks/src/benchmarks/regression/CharsetBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/CharsetBenchmark.java
@@ -68,65 +68,6 @@
}
}
- // FIXME: benchmark this pure-java implementation for US-ASCII and ISO-8859-1 too!
-
- /**
- * Translates the given characters to US-ASCII or ISO-8859-1 bytes, using the fact that
- * Unicode code points between U+0000 and U+007f inclusive are identical to US-ASCII, while
- * U+0000 to U+00ff inclusive are identical to ISO-8859-1.
- */
- private static byte[] toDirectMappedBytes(char[] chars, int offset, int length, int maxValidChar) {
- byte[] result = new byte[length];
- int o = offset;
- for (int i = 0; i < length; ++i) {
- int ch = chars[o++];
- result[i] = (byte) ((ch <= maxValidChar) ? ch : '?');
- }
- return result;
- }
-
- private static byte[] toUtf8Bytes(char[] chars, int offset, int length) {
- UnsafeByteSequence result = new UnsafeByteSequence(length);
- toUtf8Bytes(chars, offset, length, result);
- return result.toByteArray();
- }
-
- private static void toUtf8Bytes(char[] chars, int offset, int length, UnsafeByteSequence out) {
- final int end = offset + length;
- for (int i = offset; i < end; ++i) {
- int ch = chars[i];
- if (ch < 0x80) {
- // One byte.
- out.write(ch);
- } else if (ch < 0x800) {
- // Two bytes.
- out.write((ch >> 6) | 0xc0);
- out.write((ch & 0x3f) | 0x80);
- } else if (ch >= Character.MIN_SURROGATE && ch <= Character.MAX_SURROGATE) {
- // A supplementary character.
- char high = (char) ch;
- char low = (i + 1 != end) ? chars[i + 1] : '\u0000';
- if (!Character.isSurrogatePair(high, low)) {
- out.write('?');
- continue;
- }
- // Now we know we have a *valid* surrogate pair, we can consume the low surrogate.
- ++i;
- ch = Character.toCodePoint(high, low);
- // Four bytes.
- out.write((ch >> 18) | 0xf0);
- out.write(((ch >> 12) & 0x3f) | 0x80);
- out.write(((ch >> 6) & 0x3f) | 0x80);
- out.write((ch & 0x3f) | 0x80);
- } else {
- // Three bytes.
- out.write((ch >> 12) | 0xe0);
- out.write(((ch >> 6) & 0x3f) | 0x80);
- out.write((ch & 0x3f) | 0x80);
- }
- }
- }
-
private static String makeString(int length) {
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; ++i) {
diff --git a/benchmarks/src/benchmarks/regression/DateIntervalFormatBenchmark.java b/benchmarks/src/benchmarks/regression/DateIntervalFormatBenchmark.java
new file mode 100644
index 0000000..02d8f97
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/DateIntervalFormatBenchmark.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 Google Inc.
+ *
+ * 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 benchmarks.regression;
+
+import com.google.caliper.SimpleBenchmark;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static libcore.icu.DateIntervalFormat.*;
+
+public class DateIntervalFormatBenchmark extends SimpleBenchmark {
+ public void timeDateIntervalFormat_formatDateRange_DATE(int reps) throws Exception {
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+ int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY;
+
+ for (int rep = 0; rep < reps; ++rep) {
+ formatDateRange(l, utc, 0L, 0L, flags);
+ }
+ }
+
+ public void timeDateIntervalFormat_formatDateRange_TIME(int reps) throws Exception {
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+ int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR;
+
+ for (int rep = 0; rep < reps; ++rep) {
+ formatDateRange(l, utc, 0L, 0L, flags);
+ }
+ }
+
+ public void timeDateIntervalFormat_formatDateRange_DATE_TIME(int reps) throws Exception {
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+ int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_TIME | FORMAT_24HOUR;
+
+ for (int rep = 0; rep < reps; ++rep) {
+ formatDateRange(l, utc, 0L, 0L, flags);
+ }
+ }
+}
diff --git a/benchmarks/src/benchmarks/regression/IcuBenchmark.java b/benchmarks/src/benchmarks/regression/IcuBenchmark.java
new file mode 100644
index 0000000..ee8270a
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/IcuBenchmark.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013 Google Inc.
+ *
+ * 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 benchmarks.regression;
+
+import com.google.caliper.SimpleBenchmark;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+import libcore.icu.ICU;
+
+public class IcuBenchmark extends SimpleBenchmark {
+ public void time_getBestDateTimePattern(int reps) throws Exception {
+ for (int rep = 0; rep < reps; ++rep) {
+ ICU.getBestDateTimePattern("dEEEMMM", "US");
+ }
+ }
+}
diff --git a/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java b/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
index ed37fd6..7a6c92c 100644
--- a/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
+++ b/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
@@ -161,11 +161,11 @@
if (keyAlgorithm == null) {
continue;
}
- String sigAlgorithm;
+ final String sigAlgorithm;
// handle cases like EC_EC and EC_RSA
int index = keyAlgorithm.indexOf('_');
if (index == -1) {
- sigAlgorithm = keyAlgorithm;
+ sigAlgorithm = null;
} else {
sigAlgorithm = keyAlgorithm.substring(index + 1);
keyAlgorithm = keyAlgorithm.substring(0, index);
@@ -181,7 +181,8 @@
* "SHA1WithECDSA" or simply "ECDSA".
*/
// sig algorithm does not match
- if (certSigAlg != null && !certSigAlg.contains(sigAlgorithm)) {
+ if (sigAlgorithm != null && certSigAlg != null
+ && !certSigAlg.contains(sigAlgorithm)) {
continue;
}
// no issuers to match, just add to return list and continue
diff --git a/crypto/src/main/java/org/conscrypt/NativeCrypto.java b/crypto/src/main/java/org/conscrypt/NativeCrypto.java
index b6c6796..f60e286 100644
--- a/crypto/src/main/java/org/conscrypt/NativeCrypto.java
+++ b/crypto/src/main/java/org/conscrypt/NativeCrypto.java
@@ -46,11 +46,12 @@
// --- OpenSSL library initialization --------------------------------------
static {
/*
- * If we're compiled as part of Android, we don't need to explicitly
- * call loadLibrary. Detect this by looking for the jarjar'd package
- * name.
+ * If we're compiled as part of Android, should use a different JNI
+ * library name. Detect this by looking for the jarjar'd package name.
*/
- if (!"com.android.org.conscrypt".equals(NativeCrypto.class.getPackage().getName())) {
+ if ("com.android.org.conscrypt".equals(NativeCrypto.class.getPackage().getName())) {
+ System.loadLibrary("javacrypto");
+ } else {
System.loadLibrary("conscrypt_jni");
}
diff --git a/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
index 632f9e2..7acccc7 100644
--- a/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
@@ -16,6 +16,7 @@
package org.conscrypt;
+import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -118,6 +119,11 @@
}
/**
+ * Returns the standard name for the particular algorithm.
+ */
+ protected abstract String getBaseCipherName();
+
+ /**
* Returns the OpenSSL cipher name for the particular {@code keySize} and
* cipher {@code mode}.
*/
@@ -214,10 +220,22 @@
@Override
protected AlgorithmParameters engineGetParameters() {
+ if (iv != null && iv.length > 0) {
+ try {
+ AlgorithmParameters params = AlgorithmParameters.getInstance(getBaseCipherName());
+ params.init(iv);
+ return params;
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
return null;
}
- private void engineInitInternal(int opmode, Key key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException {
+ private void engineInitInternal(int opmode, Key key, byte[] iv, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE) {
encrypting = true;
} else if (opmode == Cipher.DECRYPT_MODE || opmode == Cipher.UNWRAP_MODE) {
@@ -245,9 +263,15 @@
}
final int ivLength = NativeCrypto.EVP_CIPHER_iv_length(cipherType);
- if (iv == null) {
+ if (iv == null && ivLength != 0) {
iv = new byte[ivLength];
- } else if (iv.length != ivLength) {
+ if (encrypting) {
+ if (random == null) {
+ random = new SecureRandom();
+ }
+ random.nextBytes(iv);
+ }
+ } else if (iv != null && iv.length != ivLength) {
throw new InvalidAlgorithmParameterException("expected IV length of " + ivLength);
}
@@ -273,7 +297,7 @@
@Override
protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
try {
- engineInitInternal(opmode, key, null);
+ engineInitInternal(opmode, key, null, random);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
@@ -290,7 +314,7 @@
iv = null;
}
- engineInitInternal(opmode, key, iv);
+ engineInitInternal(opmode, key, iv, random);
}
@Override
@@ -631,6 +655,11 @@
}
@Override
+ protected String getBaseCipherName() {
+ return "AES";
+ }
+
+ @Override
protected String getCipherName(int keyLength, Mode mode) {
return "aes-" + (keyLength * 8) + "-" + mode.toString().toLowerCase(Locale.US);
}
@@ -721,6 +750,11 @@
}
@Override
+ protected String getBaseCipherName() {
+ return "DESede";
+ }
+
+ @Override
protected String getCipherName(int keySize, Mode mode) {
final String baseCipherName;
if (keySize == 16) {
@@ -780,6 +814,11 @@
}
@Override
+ protected String getBaseCipherName() {
+ return "ARCFOUR";
+ }
+
+ @Override
protected String getCipherName(int keySize, Mode mode) {
return "rc4";
}
diff --git a/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
index a4b41db..4010ec5 100644
--- a/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
@@ -78,11 +78,29 @@
@Override
public String getFormat() {
+ /*
+ * If we're using an OpenSSL ENGINE, there's no guarantee we can export
+ * the key. Returning {@code null} tells the caller that there's no
+ * encoded format.
+ */
+ if (key.isEngineBased()) {
+ return null;
+ }
+
return "PKCS#8";
}
@Override
public byte[] getEncoded() {
+ /*
+ * If we're using an OpenSSL ENGINE, there's no guarantee we can export
+ * the key. Returning {@code null} tells the caller that there's no
+ * encoded format.
+ */
+ if (key.isEngineBased()) {
+ return null;
+ }
+
return NativeCrypto.i2d_PKCS8_PRIV_KEY_INFO(key.getPkeyContext());
}
diff --git a/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java b/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java
index 7314478..4055e50 100644
--- a/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java
@@ -36,6 +36,9 @@
public OpenSSLProvider() {
super(PROVIDER_NAME, 1.0, "Android's OpenSSL-backed security provider");
+ // Make sure the platform is initialized.
+ Platform.setup();
+
final String prefix = getClass().getPackage().getName() + ".";
/* === SSL Contexts === */
diff --git a/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
index ea64ee3..4b705d7 100644
--- a/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
@@ -507,6 +507,11 @@
return;
}
+ // Note that OpenSSL says to use SSL_use_certificate before SSL_use_PrivateKey.
+
+ byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
+ NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes);
+
try {
final OpenSSLKey key = OpenSSLKey.fromPrivateKey(privateKey);
NativeCrypto.SSL_use_PrivateKey(sslNativePointer, key.getPkeyContext());
@@ -514,9 +519,6 @@
throw new SSLException(e);
}
- byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
- NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes);
-
// checks the last installed private key and certificate,
// so need to do this once per loop iteration
NativeCrypto.SSL_check_private_key(sslNativePointer);
diff --git a/crypto/src/main/java/org/conscrypt/PinFailureLogger.java b/crypto/src/main/java/org/conscrypt/PinFailureLogger.java
index 67bbc1f..bdb44a9 100644
--- a/crypto/src/main/java/org/conscrypt/PinFailureLogger.java
+++ b/crypto/src/main/java/org/conscrypt/PinFailureLogger.java
@@ -59,7 +59,7 @@
}
sb.append("|");
}
- DropBox.addText("cert_pin_failure", sb.toString());
+ DropBox.addText("exp_det_cert_pin_failure", sb.toString());
}
protected static boolean timeToLog() {
diff --git a/crypto/src/main/java/org/conscrypt/Platform.java b/crypto/src/main/java/org/conscrypt/Platform.java
new file mode 100644
index 0000000..3a577ce
--- /dev/null
+++ b/crypto/src/main/java/org/conscrypt/Platform.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013 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 org.conscrypt;
+
+import org.apache.harmony.security.utils.AlgNameMapper;
+import org.apache.harmony.security.utils.AlgNameMapperSource;
+
+class Platform {
+ private static class NoPreloadHolder {
+ public static final Platform MAPPER = new Platform();
+ }
+
+ /**
+ * Runs all the setup for the platform that only needs to run once.
+ */
+ public static void setup() {
+ NoPreloadHolder.MAPPER.ping();
+ }
+
+ /**
+ * Just a placeholder to make sure the class is initialized.
+ */
+ private void ping() {
+ }
+
+ private Platform() {
+ AlgNameMapper.setSource(new OpenSSLMapper());
+ }
+
+ private static class OpenSSLMapper implements AlgNameMapperSource {
+ @Override
+ public String mapNameToOid(String algName) {
+ return NativeCrypto.OBJ_txt2nid_oid(algName);
+ }
+
+ @Override
+ public String mapOidToName(String oid) {
+ return NativeCrypto.OBJ_txt2nid_longName(oid);
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
index 8a59fdc..cc5abbd 100644
--- a/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
+++ b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
@@ -47,6 +47,7 @@
#include <openssl/x509v3.h>
#include "AsynchronousSocketCloseMonitor.h"
+#include "cutils/log.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -252,9 +253,8 @@
X509Chain(size_t n) : x509s_(n) {}
~X509Chain() {
- // TODO: C++0x auto
- for (std::vector<X509*>::const_iterator it = x509s_.begin(); it != x509s_.end(); ++it) {
- X509_free(*it);
+ for (const auto& x509 : x509s_) {
+ X509_free(x509);
}
}
@@ -292,6 +292,7 @@
struct sk_SSL_CIPHER_Delete {
void operator()(STACK_OF(SSL_CIPHER)* p) const {
+ // We don't own SSL_CIPHER references, so no need for pop_free
sk_SSL_CIPHER_free(p);
}
};
@@ -299,28 +300,28 @@
struct sk_X509_Delete {
void operator()(STACK_OF(X509)* p) const {
- sk_X509_free(p);
+ sk_X509_pop_free(p, X509_free);
}
};
typedef UniquePtr<STACK_OF(X509), sk_X509_Delete> Unique_sk_X509;
struct sk_X509_NAME_Delete {
void operator()(STACK_OF(X509_NAME)* p) const {
- sk_X509_NAME_free(p);
+ sk_X509_NAME_pop_free(p, X509_NAME_free);
}
};
typedef UniquePtr<STACK_OF(X509_NAME), sk_X509_NAME_Delete> Unique_sk_X509_NAME;
struct sk_ASN1_OBJECT_Delete {
void operator()(STACK_OF(ASN1_OBJECT)* p) const {
- sk_ASN1_OBJECT_free(p);
+ sk_ASN1_OBJECT_pop_free(p, ASN1_OBJECT_free);
}
};
typedef UniquePtr<STACK_OF(ASN1_OBJECT), sk_ASN1_OBJECT_Delete> Unique_sk_ASN1_OBJECT;
struct sk_GENERAL_NAME_Delete {
void operator()(STACK_OF(GENERAL_NAME)* p) const {
- sk_GENERAL_NAME_free(p);
+ sk_GENERAL_NAME_pop_free(p, GENERAL_NAME_free);
}
};
typedef UniquePtr<STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_Delete> Unique_sk_GENERAL_NAME;
@@ -417,6 +418,7 @@
throwBadPaddingException(env, message);
break;
case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
+ case EVP_R_WRONG_FINAL_BLOCK_LENGTH:
throwIllegalBlockSizeException(env, message);
break;
case EVP_R_BAD_KEY_LENGTH:
@@ -856,6 +858,14 @@
}
/**
+ * To avoid the round-trip to ASN.1 and back in X509_dup, we just up the reference count.
+ */
+static X509* X509_dup_nocopy(X509* x509) {
+ CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
+ return x509;
+}
+
+/**
* BIO for InputStream
*/
class BIO_Stream {
@@ -999,7 +1009,7 @@
return -1;
}
- return 1;
+ return len;
}
};
@@ -3620,7 +3630,7 @@
return;
}
- EVP_CIPHER_CTX_set_padding(ctx, enablePadding);
+ EVP_CIPHER_CTX_set_padding(ctx, enablePadding); // Not void, but always returns 1.
JNI_TRACE("EVP_CIPHER_CTX_set_padding(%p, %d) => success", ctx, enablePadding);
}
@@ -3635,16 +3645,24 @@
return;
}
- EVP_CIPHER_CTX_set_key_length(ctx, keySizeBits);
+ if (!EVP_CIPHER_CTX_set_key_length(ctx, keySizeBits)) {
+ throwExceptionIfNecessary(env, "NativeCrypto_EVP_CIPHER_CTX_set_key_length");
+ JNI_TRACE("NativeCrypto_EVP_CIPHER_CTX_set_key_length => threw error");
+ return;
+ }
JNI_TRACE("EVP_CIPHER_CTX_set_key_length(%p, %d) => success", ctx, keySizeBits);
}
-static void NativeCrypto_EVP_CIPHER_CTX_cleanup(JNIEnv*, jclass, jlong ctxRef) {
+static void NativeCrypto_EVP_CIPHER_CTX_cleanup(JNIEnv* env, jclass, jlong ctxRef) {
EVP_CIPHER_CTX* ctx = reinterpret_cast<EVP_CIPHER_CTX*>(ctxRef);
JNI_TRACE("EVP_CIPHER_CTX_cleanup(%p)", ctx);
if (ctx != NULL) {
- EVP_CIPHER_CTX_cleanup(ctx);
+ if (!EVP_CIPHER_CTX_cleanup(ctx)) {
+ throwExceptionIfNecessary(env, "EVP_CIPHER_CTX_cleanup");
+ JNI_TRACE("EVP_CIPHER_CTX_cleanup => threw error");
+ return;
+ }
}
JNI_TRACE("EVP_CIPHER_CTX_cleanup(%p) => success", ctx);
}
@@ -3681,7 +3699,7 @@
}
unsigned char* tmp = reinterpret_cast<unsigned char*>(outputBytes.get());
- if (!RAND_bytes(tmp, outputBytes.size())) {
+ if (RAND_bytes(tmp, outputBytes.size()) <= 0) {
throwExceptionIfNecessary(env, "NativeCrypto_RAND_bytes");
JNI_TRACE("tmp=%p NativeCrypto_RAND_bytes => threw error", tmp);
return;
@@ -3844,7 +3862,7 @@
}
env->GetByteArrayRegion(inputJavaBytes, offset, length, reinterpret_cast<jbyte*>(buffer.get()));
- if (BIO_write(bio, buffer.get(), length) != 1) {
+ if (BIO_write(bio, buffer.get(), length) != length) {
freeOpenSslErrorState();
jniThrowException(env, "java/io/IOException", "BIO_write");
JNI_TRACE("BIO_write(%p, %p, %d, %d) => IO error", bio, inputJavaBytes, offset, length);
@@ -4381,8 +4399,12 @@
return;
}
- X509_CRL_print(bio, crl);
- JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
+ if (!X509_CRL_print(bio, crl)) {
+ throwExceptionIfNecessary(env, "X509_CRL_print");
+ JNI_TRACE("X509_CRL_print(%p, %p) => threw error", bio, crl);
+ } else {
+ JNI_TRACE("X509_CRL_print(%p, %p) => success", bio, crl);
+ }
}
static jstring NativeCrypto_get_X509_CRL_sig_alg_oid(JNIEnv* env, jclass, jlong x509CrlRef) {
@@ -4526,6 +4548,8 @@
return reinterpret_cast<uintptr_t>(revoked->revocationDate);
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wwrite-strings"
static void NativeCrypto_X509_REVOKED_print(JNIEnv* env, jclass, jlong bioRef, jlong x509RevokedRef) {
BIO* bio = reinterpret_cast<BIO*>(static_cast<uintptr_t>(bioRef));
X509_REVOKED* revoked = reinterpret_cast<X509_REVOKED*>(static_cast<uintptr_t>(x509RevokedRef));
@@ -4543,16 +4567,14 @@
return;
}
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wwrite-strings"
BIO_printf(bio, "Serial Number: ");
i2a_ASN1_INTEGER(bio, revoked->serialNumber);
BIO_printf(bio, "\nRevocation Date: ");
ASN1_TIME_print(bio, revoked->revocationDate);
BIO_printf(bio, "\n");
X509V3_extensions_print(bio, "CRL entry extensions", revoked->extensions, 0, 0);
-#pragma GCC diagnostic pop
}
+#pragma GCC diagnostic pop
static jbyteArray NativeCrypto_get_X509_CRL_crl_enc(JNIEnv* env, jclass, jlong x509CrlRef) {
X509_CRL* crl = reinterpret_cast<X509_CRL*>(static_cast<uintptr_t>(x509CrlRef));
@@ -4950,7 +4972,7 @@
ScopedLocalRef<jlongArray> certArray(env, env->NewLongArray(size));
ScopedLongArrayRW certs(env, certArray.get());
for (size_t i = 0; i < size; i++) {
- X509* item = reinterpret_cast<X509*>(sk_X509_value(path.get(), i));
+ X509* item = reinterpret_cast<X509*>(sk_X509_shift(path.get()));
certs[i] = reinterpret_cast<uintptr_t>(item);
}
@@ -4974,7 +4996,7 @@
for (size_t i = 0; i < certsArray.size(); i++) {
X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(certsArray[i]));
- sk_X509_push(certStack.get(), X509_dup(x509));
+ sk_X509_push(certStack.get(), X509_dup_nocopy(x509));
}
int len;
@@ -5079,8 +5101,12 @@
return;
}
- X509_print_ex(bio, x509, nmflag, certflag);
- JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
+ if (!X509_print_ex(bio, x509, nmflag, certflag)) {
+ throwExceptionIfNecessary(env, "X509_print_ex");
+ JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => threw error", bio, x509, nmflag, certflag);
+ } else {
+ JNI_TRACE("X509_print_ex(%p, %p, %ld, %ld) => success", bio, x509, nmflag, certflag);
+ }
}
static jlong NativeCrypto_X509_get_pubkey(JNIEnv* env, jclass, jlong x509Ref) {
@@ -5593,6 +5619,7 @@
if (fdsEmergency[1] != -1) {
close(fdsEmergency[1]);
}
+ clearCallbackState();
MUTEX_CLEANUP(mutex);
}
@@ -5640,20 +5667,22 @@
sslHandshakeCallbacks = shc;
fileDescriptor = fd;
if (npnProtocols != NULL) {
- npnProtocolsArray = npnProtocols;
- npnProtocolsLength = e->GetArrayLength(npnProtocols);
npnProtocolsData = e->GetByteArrayElements(npnProtocols, NULL);
if (npnProtocolsData == NULL) {
+ clearCallbackState();
return false;
}
+ npnProtocolsArray = npnProtocols;
+ npnProtocolsLength = e->GetArrayLength(npnProtocols);
}
if (alpnProtocols != NULL) {
- alpnProtocolsArray = alpnProtocols;
- alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
if (alpnProtocolsData == NULL) {
+ clearCallbackState();
return false;
}
+ alpnProtocolsArray = alpnProtocols;
+ alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
}
return true;
}
@@ -6768,6 +6797,7 @@
switch (status) {
case OPENSSL_NPN_NEGOTIATED:
JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
+ return SSL_TLSEXT_ERR_OK;
break;
case OPENSSL_NPN_UNSUPPORTED:
JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
@@ -6777,9 +6807,13 @@
break;
}
} else {
+ if (out != NULL && outLength != NULL) {
+ *out = NULL;
+ *outLength = 0;
+ }
JNI_TRACE("protocols=NULL");
}
- return SSL_TLSEXT_ERR_OK;
+ return SSL_TLSEXT_ERR_NOACK;
}
/**
@@ -6829,8 +6863,12 @@
if (npnProtocols != NULL) {
*out = npnProtocols;
*outlen = appData->npnProtocolsLength;
+ return SSL_TLSEXT_ERR_OK;
+ } else {
+ *out = NULL;
+ *outlen = 0;
+ return SSL_TLSEXT_ERR_NOACK;
}
- return SSL_TLSEXT_ERR_OK;
}
static void NativeCrypto_SSL_CTX_enable_npn(JNIEnv* env, jclass, jlong ssl_ctx_address)
@@ -7217,14 +7255,14 @@
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
return NULL;
}
- if (!sk_X509_push(chain.get(), certificate)) {
+ if (!sk_X509_push(chain.get(), X509_dup_nocopy(certificate))) {
jniThrowOutOfMemory(env, "Unable to push local certificate");
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
return NULL;
}
STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
for (int i=0; i<sk_X509_num(cert_chain); i++) {
- if (!sk_X509_push(chain.get(), sk_X509_value(cert_chain, i))) {
+ if (!sk_X509_push(chain.get(), X509_dup_nocopy(sk_X509_value(cert_chain, i)))) {
jniThrowOutOfMemory(env, "Unable to push local certificate chain");
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
return NULL;
@@ -7252,13 +7290,21 @@
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => NULL", ssl);
return NULL;
}
- chain_copy.reset(sk_X509_dup(chain));
+ chain_copy.reset(sk_X509_new_null());
if (chain_copy.get() == NULL) {
jniThrowOutOfMemory(env, "Unable to allocate peer certificate chain");
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
return NULL;
}
- if (!sk_X509_push(chain_copy.get(), x509)) {
+ size_t chain_size = sk_X509_num(chain);
+ for (size_t i = 0; i < chain_size; i++) {
+ if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(sk_X509_value(chain, i)))) {
+ jniThrowOutOfMemory(env, "Unable to push server's peer certificate chain");
+ JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate chain push error", ssl);
+ return NULL;
+ }
+ }
+ if (!sk_X509_push(chain_copy.get(), X509_dup_nocopy(x509))) {
jniThrowOutOfMemory(env, "Unable to push server's peer certificate");
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
return NULL;
@@ -8163,8 +8209,6 @@
outputStream_flushMethod = env->GetMethodID(outputStreamClass, "flush", "()V");
}
-#if defined(CONSCRYPT_UNBUNDLED)
-
static jclass findClass(JNIEnv* env, const char* name) {
ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
@@ -8176,7 +8220,7 @@
}
// Use JNI_OnLoad for when we're standalone
-int JNI_OnLoad(JavaVM *vm, void* reserved) {
+int JNI_OnLoad(JavaVM *vm, void*) {
JNI_TRACE("JNI_OnLoad NativeCrypto");
gJavaVM = vm;
@@ -8198,24 +8242,3 @@
initialize_conscrypt(env);
return JNI_VERSION_1_6;
}
-
-#else
-
-// Use this when built into Android
-void register_org_conscrypt_NativeCrypto(JNIEnv* env) {
- JNI_TRACE("register_org_conscrypt_NativeCrypto");
-
- byteArrayClass = JniConstants::byteArrayClass;
- calendarClass = JniConstants::calendarClass;
- inputStreamClass = JniConstants::inputStreamClass;
- integerClass = JniConstants::integerClass;
- objectClass = JniConstants::objectClass;
- objectArrayClass = JniConstants::objectArrayClass;
- outputStreamClass = JniConstants::outputStreamClass;
- stringClass = JniConstants::stringClass;
-
- env->GetJavaVM(&gJavaVM);
- initialize_conscrypt(env);
-}
-
-#endif // defined(CONSCRYPT_UNBUNDLED)
diff --git a/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java b/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
index 8692f8a..1118a49 100644
--- a/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
+++ b/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
@@ -337,6 +337,8 @@
}
public void test_SSL_use_PrivateKey_for_tls_channel_id() throws Exception {
+ initChannelIdKey();
+
try {
NativeCrypto.SSL_set1_tls_channel_id(NULL, NULL);
fail();
diff --git a/libdvm/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
similarity index 90%
rename from libdvm/src/main/java/dalvik/system/BaseDexClassLoader.java
rename to dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
index d3ec95a..6a1a493 100644
--- a/libdvm/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
@@ -18,7 +18,9 @@
import java.io.File;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.List;
/**
* Base class for common functionality between various dex-based
@@ -48,9 +50,14 @@
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
- Class c = pathList.findClass(name);
+ List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
+ Class c = pathList.findClass(name, suppressedExceptions);
if (c == null) {
- throw new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
+ ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
+ for (Throwable t : suppressedExceptions) {
+ cnfe.addSuppressed(t);
+ }
+ throw cnfe;
}
return c;
}
diff --git a/libdvm/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
similarity index 87%
rename from libdvm/src/main/java/dalvik/system/DexFile.java
rename to dalvik/src/main/java/dalvik/system/DexFile.java
index 18b730b..d2fd5da 100644
--- a/libdvm/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -19,7 +19,9 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.List;
import libcore.io.ErrnoException;
import libcore.io.Libcore;
import libcore.io.StructStat;
@@ -169,9 +171,11 @@
* normally should not happen
*/
public void close() throws IOException {
- guard.close();
- closeDexFile(mCookie);
- mCookie = 0;
+ if (mCookie != 0) {
+ guard.close();
+ closeDexFile(mCookie);
+ mCookie = 0;
+ }
}
/**
@@ -197,7 +201,7 @@
*/
public Class loadClass(String name, ClassLoader loader) {
String slashName = name.replace('.', '/');
- return loadClassBinaryName(slashName, loader);
+ return loadClassBinaryName(slashName, loader, null);
}
/**
@@ -207,11 +211,29 @@
*
* @hide
*/
- public Class loadClassBinaryName(String name, ClassLoader loader) {
- return defineClass(name, loader, mCookie);
+ public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) {
+ return defineClass(name, loader, mCookie, suppressed);
}
- private native static Class defineClass(String name, ClassLoader loader, int cookie);
+ private static Class defineClass(String name, ClassLoader loader, int cookie,
+ List<Throwable> suppressed) {
+ Class result = null;
+ try {
+ result = defineClassNative(name, loader, cookie);
+ } catch (NoClassDefFoundError e) {
+ if (suppressed != null) {
+ suppressed.add(e);
+ }
+ } catch (ClassNotFoundException e) {
+ if (suppressed != null) {
+ suppressed.add(e);
+ }
+ }
+ return result;
+ }
+
+ private static native Class defineClassNative(String name, ClassLoader loader, int cookie)
+ throws ClassNotFoundException, NoClassDefFoundError;
/**
* Enumerate the names of the classes in this DEX file.
@@ -269,7 +291,14 @@
* Open a DEX file. The value returned is a magic VM cookie. On
* failure, an IOException is thrown.
*/
- native private static int openDexFile(String sourceName, String outputName,
+ private static int openDexFile(String sourceName, String outputName,
+ int flags) throws IOException {
+ return openDexFileNative(new File(sourceName).getCanonicalPath(),
+ (outputName == null) ? null : new File(outputName).getCanonicalPath(),
+ flags);
+ }
+
+ native private static int openDexFileNative(String sourceName, String outputName,
int flags) throws IOException;
/*
diff --git a/libdvm/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
similarity index 89%
rename from libdvm/src/main/java/dalvik/system/DexPathList.java
rename to dalvik/src/main/java/dalvik/system/DexPathList.java
index a10e90e..ff0be41 100644
--- a/libdvm/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -24,7 +24,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
-import java.util.regex.Pattern;
+import java.util.List;
import java.util.zip.ZipFile;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
@@ -65,6 +65,11 @@
private final File[] nativeLibraryDirectories;
/**
+ * Exceptions thrown during creation of the dexElements list.
+ */
+ private final IOException[] dexElementsSuppressedExceptions;
+
+ /**
* Constructs an instance.
*
* @param definingContext the context in which any as-yet unresolved
@@ -103,7 +108,15 @@
}
this.definingContext = definingContext;
- this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory);
+ ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
+ this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
+ suppressedExceptions);
+ if (suppressedExceptions.size() > 0) {
+ this.dexElementsSuppressedExceptions =
+ suppressedExceptions.toArray(new IOException[suppressedExceptions.size()]);
+ } else {
+ dexElementsSuppressedExceptions = null;
+ }
this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
}
@@ -137,17 +150,13 @@
* do not refer to existing and readable directories.
*/
private static File[] splitLibraryPath(String path) {
- /*
- * Native libraries may exist in both the system and
- * application library paths, and we use this search order:
- *
- * 1. this class loader's library path for application
- * libraries
- * 2. the VM's library path from the system
- * property for system libraries
- *
- * This order was reversed prior to Gingerbread; see http://b/2933456.
- */
+ // Native libraries may exist in both the system and
+ // application library paths, and we use this search order:
+ //
+ // 1. this class loader's library path for application libraries
+ // 2. the VM's library path from the system property for system libraries
+ //
+ // This order was reversed prior to Gingerbread; see http://b/2933456.
ArrayList<File> result = splitPaths(path, System.getProperty("java.library.path"), true);
return result.toArray(new File[result.size()]);
}
@@ -194,10 +203,9 @@
* Makes an array of dex/resource path elements, one per element of
* the given array.
*/
- private static Element[] makeDexElements(ArrayList<File> files,
- File optimizedDirectory) {
+ private static Element[] makeDexElements(ArrayList<File> files, File optimizedDirectory,
+ ArrayList<IOException> suppressedExceptions) {
ArrayList<Element> elements = new ArrayList<Element>();
-
/*
* Open all files and load the (direct or contained) dex files
* up front.
@@ -220,14 +228,14 @@
try {
dex = loadDexFile(file, optimizedDirectory);
- } catch (IOException ignored) {
+ } catch (IOException suppressed) {
/*
- * IOException might get thrown "legitimately" by
- * the DexFile constructor if the zip file turns
- * out to be resource-only (that is, no
- * classes.dex file in it). Safe to just ignore
- * the exception here, and let dex == null.
+ * IOException might get thrown "legitimately" by the DexFile constructor if the
+ * zip file turns out to be resource-only (that is, no classes.dex file in it).
+ * Let dex == null and hang on to the exception to add to the tea-leaves for
+ * when findClass returns null.
*/
+ suppressedExceptions.add(suppressed);
}
} else if (file.isDirectory()) {
// We support directories for looking up resources.
@@ -301,21 +309,25 @@
* defined, then this method will define it in the defining
* context that this instance was constructed with.
*
+ * @param name of class to find
+ * @param suppressed exceptions encountered whilst finding the class
* @return the named class or {@code null} if the class is not
* found in any of the dex files
*/
- public Class findClass(String name) {
+ public Class findClass(String name, List<Throwable> suppressed) {
for (Element element : dexElements) {
DexFile dex = element.dexFile;
if (dex != null) {
- Class clazz = dex.loadClassBinaryName(name, definingContext);
+ Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
if (clazz != null) {
return clazz;
}
}
}
-
+ if (dexElementsSuppressedExceptions != null) {
+ suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
+ }
return null;
}
diff --git a/libdvm/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java
similarity index 84%
rename from libdvm/src/main/java/dalvik/system/VMDebug.java
rename to dalvik/src/main/java/dalvik/system/VMDebug.java
index a80cfcc..a46119f 100644
--- a/libdvm/src/main/java/dalvik/system/VMDebug.java
+++ b/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -30,14 +30,6 @@
*/
public final class VMDebug {
/**
- * Specifies the default method trace data file name.
- *
- * @deprecated Only used in one place, which is unused and deprecated.
- */
- @Deprecated
- static public final String DEFAULT_METHOD_TRACE_FILE_NAME = "/sdcard/dmtrace.trace";
-
- /**
* flag for startMethodTracing(), which adds the results from
* startAllocCounting to the trace key file.
*/
@@ -144,7 +136,7 @@
*/
@Deprecated
public static void startMethodTracing() {
- startMethodTracing(DEFAULT_METHOD_TRACE_FILE_NAME, 0, 0);
+ throw new UnsupportedOperationException();
}
/**
@@ -166,12 +158,7 @@
* is currently defined is {@link #TRACE_COUNT_ALLOCS}.
*/
public static void startMethodTracing(String traceFileName, int bufferSize, int flags) {
-
- if (traceFileName == null) {
- throw new NullPointerException("traceFileName == null");
- }
-
- startMethodTracingNative(traceFileName, null, bufferSize, flags);
+ startMethodTracingFilename(traceFileName, checkBufferSize(bufferSize), flags);
}
/**
@@ -179,17 +166,11 @@
* FileDescriptor in which the trace is written. The file name is also
* supplied simply for logging. Makes a dup of the file descriptor.
*/
- public static void startMethodTracing(String traceFileName,
- FileDescriptor fd, int bufferSize, int flags)
- {
- if (traceFileName == null) {
- throw new NullPointerException("traceFileName == null");
- }
+ public static void startMethodTracing(String traceFileName, FileDescriptor fd, int bufferSize, int flags) {
if (fd == null) {
throw new NullPointerException("fd == null");
}
-
- startMethodTracingNative(traceFileName, fd, bufferSize, flags);
+ startMethodTracingFd(traceFileName, fd, checkBufferSize(bufferSize), flags);
}
/**
@@ -197,20 +178,30 @@
* is called, the result is sent directly to DDMS. (If DDMS is not
* attached when tracing ends, the profiling data will be discarded.)
*/
- public static void startMethodTracingDdms(int bufferSize, int flags) {
- startMethodTracingNative(null, null, bufferSize, flags);
+ public static void startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
+ startMethodTracingDdmsImpl(checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
}
- /**
- * Implements all startMethodTracing variants.
- */
- private static native void startMethodTracingNative(String traceFileName,
- FileDescriptor fd, int bufferSize, int flags);
+ private static int checkBufferSize(int bufferSize) {
+ if (bufferSize == 0) {
+ // Default to 8MB per the documentation.
+ bufferSize = 8 * 1024 * 1024;
+ }
+ if (bufferSize < 1024) {
+ throw new IllegalArgumentException("buffer size < 1024: " + bufferSize);
+ }
+ return bufferSize;
+ }
+
+ private static native void startMethodTracingDdmsImpl(int bufferSize, int flags, boolean samplingEnabled, int intervalUs);
+ private static native void startMethodTracingFd(String traceFileName, FileDescriptor fd, int bufferSize, int flags);
+ private static native void startMethodTracingFilename(String traceFileName, int bufferSize, int flags);
/**
- * Determine whether method tracing is currently active.
+ * Determine whether method tracing is currently active and what type is
+ * active.
*/
- public static native boolean isMethodTracingActive();
+ public static native int getMethodTracingMode();
/**
* Stops method tracing.
@@ -252,7 +243,7 @@
/**
* This method exists for binary compatibility. It was part of
- * the allocation limits API which was removed in Honeycomb.
+ * the allocation limits API which was removed in Android 3.0 (Honeycomb).
*/
@Deprecated
public static int setAllocationLimit(int limit) {
@@ -261,7 +252,7 @@
/**
* This method exists for binary compatibility. It was part of
- * the allocation limits API which was removed in Honeycomb.
+ * the allocation limits API which was removed in Android 3.0 (Honeycomb).
*/
@Deprecated
public static int setGlobalAllocationLimit(int limit) {
@@ -373,4 +364,25 @@
* @return the number of matching instances.
*/
public static native long countInstancesOfClass(Class klass, boolean assignable);
+
+ /**
+ * Export the heap per-space stats for dumpsys meminfo.
+ *
+ * The content of the array is:
+ *
+ * <pre>
+ * data[0] : the application heap space size
+ * data[1] : the application heap space allocated bytes
+ * data[2] : the application heap space free bytes
+ * data[3] : the zygote heap space size
+ * data[4] : the zygote heap space allocated size
+ * data[5] : the zygote heap space free size
+ * data[6] : the large object space size
+ * data[7] : the large object space allocated bytes
+ * data[8] : the large object space free bytes
+ * </pre>
+ *
+ * @param data the array into which the stats are written.
+ */
+ public static native void getHeapSpaceStats(long[] data);
}
diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java
index 29cd30e..116a33c 100644
--- a/dex/src/main/java/com/android/dex/Dex.java
+++ b/dex/src/main/java/com/android/dex/Dex.java
@@ -53,78 +53,19 @@
private static final int CHECKSUM_SIZE = 4;
private static final int SIGNATURE_OFFSET = CHECKSUM_OFFSET + CHECKSUM_SIZE;
private static final int SIGNATURE_SIZE = 20;
+ // Provided as a convenience to avoid a memory allocation to benefit Dalvik.
+ // Note: libcore.util.EmptyArray cannot be accessed when this code isn't run on Dalvik.
+ static final short[] EMPTY_SHORT_ARRAY = new short[0];
private ByteBuffer data;
private final TableOfContents tableOfContents = new TableOfContents();
private int nextSectionStart = 0;
-
- private static abstract class AbstractRandomAccessList<T>
- extends AbstractList<T> implements RandomAccess {
- }
-
- private List<String> strings = new AbstractRandomAccessList<String>() {
- @Override public String get(int index) {
- checkBounds(index, tableOfContents.stringIds.size);
- return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM))
- .readString();
- }
- @Override public int size() {
- return tableOfContents.stringIds.size;
- }
- };
-
- private final List<Integer> typeIds = new AbstractRandomAccessList<Integer>() {
- @Override public Integer get(int index) {
- checkBounds(index, tableOfContents.typeIds.size);
- return open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt();
- }
- @Override public int size() {
- return tableOfContents.typeIds.size;
- }
- };
-
- private final List<String> typeNames = new AbstractRandomAccessList<String>() {
- @Override public String get(int index) {
- checkBounds(index, tableOfContents.typeIds.size);
- return strings.get(typeIds.get(index));
- }
- @Override public int size() {
- return tableOfContents.typeIds.size;
- }
- };
-
- private final List<ProtoId> protoIds = new AbstractRandomAccessList<ProtoId>() {
- @Override public ProtoId get(int index) {
- checkBounds(index, tableOfContents.protoIds.size);
- return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index))
- .readProtoId();
- }
- @Override public int size() {
- return tableOfContents.protoIds.size;
- }
- };
-
- private final List<FieldId> fieldIds = new AbstractRandomAccessList<FieldId>() {
- @Override public FieldId get(int index) {
- checkBounds(index, tableOfContents.fieldIds.size);
- return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index))
- .readFieldId();
- }
- @Override public int size() {
- return tableOfContents.fieldIds.size;
- }
- };
-
- private final List<MethodId> methodIds = new AbstractRandomAccessList<MethodId>() {
- @Override public MethodId get(int index) {
- checkBounds(index, tableOfContents.methodIds.size);
- return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index))
- .readMethodId();
- }
- @Override public int size() {
- return tableOfContents.methodIds.size;
- }
- };
+ private final StringTable strings = new StringTable();
+ private final TypeIndexToDescriptorIndexTable typeIds = new TypeIndexToDescriptorIndexTable();
+ private final TypeIndexToDescriptorTable typeNames = new TypeIndexToDescriptorTable();
+ private final ProtoIdTable protoIds = new ProtoIdTable();
+ private final FieldIdTable fieldIds = new FieldIdTable();
+ private final MethodIdTable methodIds = new MethodIdTable();
/**
* Creates a new dex that reads from {@code data}. It is an error to modify
@@ -312,31 +253,7 @@
}
public Iterable<ClassDef> classDefs() {
- return new Iterable<ClassDef>() {
- public Iterator<ClassDef> iterator() {
- if (!tableOfContents.classDefs.exists()) {
- return Collections.<ClassDef>emptySet().iterator();
- }
- return new Iterator<ClassDef>() {
- private Dex.Section in = open(tableOfContents.classDefs.off);
- private int count = 0;
-
- public boolean hasNext() {
- return count < tableOfContents.classDefs.size;
- }
- public ClassDef next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- count++;
- return in.readClassDef();
- }
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
- };
+ return new ClassDefIterable();
}
public TypeList readTypeList(int offset) {
@@ -412,6 +329,187 @@
open(CHECKSUM_OFFSET).writeInt(computeChecksum());
}
+ /**
+ * Look up a field id name index from a field index. Cheaper than:
+ * {@code fieldIds().get(fieldDexIndex).getNameIndex();}
+ */
+ public int nameIndexFromFieldIndex(int fieldIndex) {
+ checkBounds(fieldIndex, tableOfContents.fieldIds.size);
+ int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ position += SizeOf.USHORT; // typeIndex
+ return data.getInt(position); // nameIndex
+ }
+
+ public int findStringIndex(String s) {
+ return Collections.binarySearch(strings, s);
+ }
+
+ public int findTypeIndex(String descriptor) {
+ return Collections.binarySearch(typeNames, descriptor);
+ }
+
+ public int findFieldIndex(FieldId fieldId) {
+ return Collections.binarySearch(fieldIds, fieldId);
+ }
+
+ public int findMethodIndex(MethodId methodId) {
+ return Collections.binarySearch(methodIds, methodId);
+ }
+
+ public int findClassDefIndexFromTypeIndex(int typeIndex) {
+ checkBounds(typeIndex, tableOfContents.typeIds.size);
+ if (!tableOfContents.classDefs.exists()) {
+ return -1;
+ }
+ for (int i = 0; i < tableOfContents.classDefs.size; i++) {
+ if (typeIndexFromClassDefIndex(i) == typeIndex) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Look up a field id type index from a field index. Cheaper than:
+ * {@code fieldIds().get(fieldDexIndex).getTypeIndex();}
+ */
+ public int typeIndexFromFieldIndex(int fieldIndex) {
+ checkBounds(fieldIndex, tableOfContents.fieldIds.size);
+ int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ return data.getShort(position) & 0xFFFF; // typeIndex
+ }
+
+ /**
+ * Look up a method id declaring class index from a method index. Cheaper than:
+ * {@code methodIds().get(methodIndex).getDeclaringClassIndex();}
+ */
+ public int declaringClassIndexFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ return data.getShort(position) & 0xFFFF; // declaringClassIndex
+ }
+
+ /**
+ * Look up a method id name index from a method index. Cheaper than:
+ * {@code methodIds().get(methodIndex).getNameIndex();}
+ */
+ public int nameIndexFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ position += SizeOf.USHORT; // protoIndex
+ return data.getInt(position); // nameIndex
+ }
+
+ /**
+ * Look up a parameter type ids from a method index. Cheaper than:
+ * {@code readTypeList(protoIds.get(methodIds().get(methodDexIndex).getProtoIndex()).getParametersOffset()).getTypes();}
+ */
+ public short[] parameterTypeIndicesFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ int protoIndex = data.getShort(position) & 0xFFFF;
+ checkBounds(protoIndex, tableOfContents.protoIds.size);
+ position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
+ position += SizeOf.UINT; // shortyIndex
+ position += SizeOf.UINT; // returnTypeIndex
+ int parametersOffset = data.getInt(position);
+ if (parametersOffset == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ position = parametersOffset;
+ int size = data.getInt(position);
+ if (size <= 0) {
+ throw new AssertionError("Unexpected parameter type list size: " + size);
+ }
+ position += SizeOf.UINT;
+ short[] types = new short[size];
+ for (int i = 0; i < size; i++) {
+ types[i] = data.getShort(position);
+ position += SizeOf.USHORT;
+ }
+ return types;
+ }
+
+ /**
+ * Look up a method id return type index from a method index. Cheaper than:
+ * {@code protoIds().get(methodIds().get(methodDexIndex).getProtoIndex()).getReturnTypeIndex();}
+ */
+ public int returnTypeIndexFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ int protoIndex = data.getShort(position) & 0xFFFF;
+ checkBounds(protoIndex, tableOfContents.protoIds.size);
+ position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
+ position += SizeOf.UINT; // shortyIndex
+ return data.getInt(position); // returnTypeIndex
+ }
+
+ /**
+ * Look up a descriptor index from a type index. Cheaper than:
+ * {@code open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt();}
+ */
+ public int descriptorIndexFromTypeIndex(int typeIndex) {
+ checkBounds(typeIndex, tableOfContents.typeIds.size);
+ int position = tableOfContents.typeIds.off + (SizeOf.TYPE_ID_ITEM * typeIndex);
+ return data.getInt(position);
+ }
+
+ /**
+ * Look up a type index index from a class def index.
+ */
+ public int typeIndexFromClassDefIndex(int classDefIndex) {
+ checkBounds(classDefIndex, tableOfContents.classDefs.size);
+ int position = tableOfContents.classDefs.off + (SizeOf.CLASS_DEF_ITEM * classDefIndex);
+ return data.getInt(position);
+ }
+
+ /**
+ * Look up a type index index from a class def index.
+ */
+ public int annotationDirectoryOffsetFromClassDefIndex(int classDefIndex) {
+ checkBounds(classDefIndex, tableOfContents.classDefs.size);
+ int position = tableOfContents.classDefs.off + (SizeOf.CLASS_DEF_ITEM * classDefIndex);
+ position += SizeOf.UINT; // type
+ position += SizeOf.UINT; // accessFlags
+ position += SizeOf.UINT; // superType
+ position += SizeOf.UINT; // interfacesOffset
+ position += SizeOf.UINT; // sourceFileIndex
+ return data.getInt(position);
+ }
+
+ /**
+ * Look up interface types indices from a return type index from a method index. Cheaper than:
+ * {@code ...getClassDef(classDefIndex).getInterfaces();}
+ */
+ public short[] interfaceTypeIndicesFromClassDefIndex(int classDefIndex) {
+ checkBounds(classDefIndex, tableOfContents.classDefs.size);
+ int position = tableOfContents.classDefs.off + (SizeOf.CLASS_DEF_ITEM * classDefIndex);
+ position += SizeOf.UINT; // type
+ position += SizeOf.UINT; // accessFlags
+ position += SizeOf.UINT; // superType
+ int interfacesOffset = data.getInt(position);
+ if (interfacesOffset == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ position = interfacesOffset;
+ int size = data.getInt(position);
+ if (size <= 0) {
+ throw new AssertionError("Unexpected interfaces list size: " + size);
+ }
+ position += SizeOf.UINT;
+ short[] types = new short[size];
+ for (int i = 0; i < size; i++) {
+ types[i] = data.getShort(position);
+ position += SizeOf.USHORT;
+ }
+ return types;
+ }
+
public final class Section implements ByteInput, ByteOutput {
private final String name;
private final ByteBuffer data;
@@ -450,6 +548,9 @@
}
public short[] readShortArray(int length) {
+ if (length == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
short[] result = new short[length];
for (int i = 0; i < length; i++) {
result[i] = readShort();
@@ -475,10 +576,7 @@
public TypeList readTypeList() {
int size = readInt();
- short[] types = new short[size];
- for (int i = 0; i < size; i++) {
- types[i] = readShort();
- }
+ short[] types = readShortArray(size);
alignToFourBytes();
return new TypeList(Dex.this, types);
}
@@ -552,71 +650,71 @@
Try[] tries;
CatchHandler[] catchHandlers;
if (triesSize > 0) {
- if (instructions.length % 2 == 1) {
- readShort(); // padding
- }
+ if (instructions.length % 2 == 1) {
+ readShort(); // padding
+ }
- /*
- * We can't read the tries until we've read the catch handlers.
- * Unfortunately they're in the opposite order in the dex file
- * so we need to read them out-of-order.
- */
- Section triesSection = open(data.position());
- skip(triesSize * SizeOf.TRY_ITEM);
- catchHandlers = readCatchHandlers();
- tries = triesSection.readTries(triesSize, catchHandlers);
- } else {
- tries = new Try[0];
- catchHandlers = new CatchHandler[0];
- }
- return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions,
- tries, catchHandlers);
+ /*
+ * We can't read the tries until we've read the catch handlers.
+ * Unfortunately they're in the opposite order in the dex file
+ * so we need to read them out-of-order.
+ */
+ Section triesSection = open(data.position());
+ skip(triesSize * SizeOf.TRY_ITEM);
+ catchHandlers = readCatchHandlers();
+ tries = triesSection.readTries(triesSize, catchHandlers);
+ } else {
+ tries = new Try[0];
+ catchHandlers = new CatchHandler[0];
+ }
+ return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions,
+ tries, catchHandlers);
}
private CatchHandler[] readCatchHandlers() {
- int baseOffset = data.position();
- int catchHandlersSize = readUleb128();
- CatchHandler[] result = new CatchHandler[catchHandlersSize];
- for (int i = 0; i < catchHandlersSize; i++) {
- int offset = data.position() - baseOffset;
- result[i] = readCatchHandler(offset);
- }
- return result;
+ int baseOffset = data.position();
+ int catchHandlersSize = readUleb128();
+ CatchHandler[] result = new CatchHandler[catchHandlersSize];
+ for (int i = 0; i < catchHandlersSize; i++) {
+ int offset = data.position() - baseOffset;
+ result[i] = readCatchHandler(offset);
+ }
+ return result;
}
private Try[] readTries(int triesSize, CatchHandler[] catchHandlers) {
- Try[] result = new Try[triesSize];
- for (int i = 0; i < triesSize; i++) {
- int startAddress = readInt();
- int instructionCount = readUnsignedShort();
- int handlerOffset = readUnsignedShort();
- int catchHandlerIndex = findCatchHandlerIndex(catchHandlers, handlerOffset);
- result[i] = new Try(startAddress, instructionCount, catchHandlerIndex);
- }
- return result;
+ Try[] result = new Try[triesSize];
+ for (int i = 0; i < triesSize; i++) {
+ int startAddress = readInt();
+ int instructionCount = readUnsignedShort();
+ int handlerOffset = readUnsignedShort();
+ int catchHandlerIndex = findCatchHandlerIndex(catchHandlers, handlerOffset);
+ result[i] = new Try(startAddress, instructionCount, catchHandlerIndex);
+ }
+ return result;
}
private int findCatchHandlerIndex(CatchHandler[] catchHandlers, int offset) {
- for (int i = 0; i < catchHandlers.length; i++) {
- CatchHandler catchHandler = catchHandlers[i];
- if (catchHandler.getOffset() == offset) {
- return i;
+ for (int i = 0; i < catchHandlers.length; i++) {
+ CatchHandler catchHandler = catchHandlers[i];
+ if (catchHandler.getOffset() == offset) {
+ return i;
+ }
}
- }
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException();
}
private CatchHandler readCatchHandler(int offset) {
- int size = readSleb128();
- int handlersCount = Math.abs(size);
- int[] typeIndexes = new int[handlersCount];
- int[] addresses = new int[handlersCount];
- for (int i = 0; i < handlersCount; i++) {
- typeIndexes[i] = readUleb128();
- addresses[i] = readUleb128();
- }
- int catchAllAddress = size <= 0 ? readUleb128() : -1;
- return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset);
+ int size = readSleb128();
+ int handlersCount = Math.abs(size);
+ int[] typeIndexes = new int[handlersCount];
+ int[] addresses = new int[handlersCount];
+ for (int i = 0; i < handlersCount; i++) {
+ typeIndexes[i] = readUleb128();
+ addresses[i] = readUleb128();
+ }
+ int catchAllAddress = size <= 0 ? readUleb128() : -1;
+ return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset);
}
private ClassData readClassData() {
@@ -680,11 +778,11 @@
}
public void skip(int count) {
- if (count < 0) {
- throw new IllegalArgumentException();
- }
- data.position(data.position() + count);
- }
+ if (count < 0) {
+ throw new IllegalArgumentException();
+ }
+ data.position(data.position() + count);
+ }
/**
* Skips bytes until the position is aligned to a multiple of 4.
@@ -788,4 +886,98 @@
return data.position() - initialPosition;
}
}
+
+ private final class StringTable extends AbstractList<String> implements RandomAccess {
+ @Override public String get(int index) {
+ checkBounds(index, tableOfContents.stringIds.size);
+ return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM))
+ .readString();
+ }
+ @Override public int size() {
+ return tableOfContents.stringIds.size;
+ }
+ };
+
+ private final class TypeIndexToDescriptorIndexTable extends AbstractList<Integer>
+ implements RandomAccess {
+ @Override public Integer get(int index) {
+ return descriptorIndexFromTypeIndex(index);
+ }
+ @Override public int size() {
+ return tableOfContents.typeIds.size;
+ }
+ };
+
+ private final class TypeIndexToDescriptorTable extends AbstractList<String>
+ implements RandomAccess {
+ @Override public String get(int index) {
+ return strings.get(descriptorIndexFromTypeIndex(index));
+ }
+ @Override public int size() {
+ return tableOfContents.typeIds.size;
+ }
+ };
+
+ private final class ProtoIdTable extends AbstractList<ProtoId> implements RandomAccess {
+ @Override public ProtoId get(int index) {
+ checkBounds(index, tableOfContents.protoIds.size);
+ return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index))
+ .readProtoId();
+ }
+ @Override public int size() {
+ return tableOfContents.protoIds.size;
+ }
+ };
+
+ private final class FieldIdTable extends AbstractList<FieldId> implements RandomAccess {
+ @Override public FieldId get(int index) {
+ checkBounds(index, tableOfContents.fieldIds.size);
+ return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index))
+ .readFieldId();
+ }
+ @Override public int size() {
+ return tableOfContents.fieldIds.size;
+ }
+ };
+
+ private final class MethodIdTable extends AbstractList<MethodId> implements RandomAccess {
+ @Override public MethodId get(int index) {
+ checkBounds(index, tableOfContents.methodIds.size);
+ return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index))
+ .readMethodId();
+ }
+ @Override public int size() {
+ return tableOfContents.methodIds.size;
+ }
+ };
+
+ private final class ClassDefIterator implements Iterator<ClassDef> {
+ private final Dex.Section in = open(tableOfContents.classDefs.off);
+ private int count = 0;
+
+ @Override
+ public boolean hasNext() {
+ return count < tableOfContents.classDefs.size;
+ }
+ @Override
+ public ClassDef next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ count++;
+ return in.readClassDef();
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ private final class ClassDefIterable implements Iterable<ClassDef> {
+ public Iterator<ClassDef> iterator() {
+ return !tableOfContents.classDefs.exists()
+ ? Collections.<ClassDef>emptySet().iterator()
+ : new ClassDefIterator();
+ }
+ };
}
diff --git a/dex/src/main/java/com/android/dex/DexFormat.java b/dex/src/main/java/com/android/dex/DexFormat.java
index 85941fd..9319bc2 100644
--- a/dex/src/main/java/com/android/dex/DexFormat.java
+++ b/dex/src/main/java/com/android/dex/DexFormat.java
@@ -56,6 +56,19 @@
public static final int ENDIAN_TAG = 0x12345678;
/**
+ * Maximum addressable field or method index.
+ * The largest addressable member is 0xffff, in the "instruction formats" spec as field@CCCC or
+ * meth@CCCC.
+ */
+ public static final int MAX_MEMBER_IDX = 0xFFFF;
+
+ /**
+ * Maximum addressable type index.
+ * The largest addressable type is 0xffff, in the "instruction formats" spec as type@CCCC.
+ */
+ public static final int MAX_TYPE_IDX = 0xFFFF;
+
+ /**
* Returns the API level corresponding to the given magic number,
* or {@code -1} if the given array is not a well-formed dex file
* magic number.
diff --git a/dex/src/main/java/com/android/dex/TypeList.java b/dex/src/main/java/com/android/dex/TypeList.java
index 6e321fb..123e82c 100644
--- a/dex/src/main/java/com/android/dex/TypeList.java
+++ b/dex/src/main/java/com/android/dex/TypeList.java
@@ -20,7 +20,7 @@
public final class TypeList implements Comparable<TypeList> {
- public static final TypeList EMPTY = new TypeList(null, new short[0]);
+ public static final TypeList EMPTY = new TypeList(null, Dex.EMPTY_SHORT_ARRAY);
private final Dex dex;
private final short[] types;
diff --git a/expectations/brokentests.txt b/expectations/brokentests.txt
index ae70c55..24813dd 100644
--- a/expectations/brokentests.txt
+++ b/expectations/brokentests.txt
@@ -793,12 +793,6 @@
substring: "junit.framework.AssertionFailedError: expected:<1.1> but was:<2.0>"
},
{
- description: "We don't permit runtime switching of the default charset (and neither does the RI)",
- result: EXEC_FAILED,
- name: "org.apache.harmony.nio_char.tests.java.nio.charset.CharsetTest#test_defaultCharset",
- substring: "expected:<ISO-8859-1> but was:<UTF-8>"
-},
-{
description: "this test needs external interaction",
result: UNSUPPORTED,
names: [
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 33f381f..5055cbf 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -3,6 +3,16 @@
*/
[
{
+ description: "four known CharsetDecoder-/CharsetEncoder-related failures",
+ names: [
+ "org.apache.harmony.nio_char.tests.java.nio.charset.ASCIICharsetEncoderTest#testCanEncodeSurrogate",
+ "org.apache.harmony.nio_char.tests.java.nio.charset.ASCIICharsetEncoderTest#testMultiStepEncode",
+ "org.apache.harmony.nio_char.tests.java.nio.charset.CharsetDecoderTest#testInvalidDecoding",
+ "org.apache.harmony.nio_char.tests.java.nio.charset.CharsetDecoderTest#test_decode"
+ ],
+ bug: 10729779
+},
+{
description: "can't compile a pattern with negative look-behind and quantifiers with upper bounds",
name: "org.apache.harmony.regex.tests.java.util.regex.PatternTest#test_bug_40103",
bug: 40103
@@ -245,16 +255,16 @@
description: "UTF-16 and UTF-32 encoders don't write big-endian output on little-endian devices",
names: [
"libcore.java.nio.charset.CharsetEncoderTest#test_defaultReplacementBytesUtf_16",
- "libcore.java.nio.charset.CharsetTest#test_UTF_16",
- "libcore.java.nio.charset.CharsetTest#test_UTF_32",
- "libcore.java.nio.charset.CharsetTest#test_UTF_16BE",
- "libcore.java.nio.charset.CharsetTest#test_UTF_16LE",
- "libcore.java.nio.charset.CharsetTest#test_UTF_32BE",
- "libcore.java.nio.charset.CharsetTest#test_UTF_32LE",
- "libcore.java.nio.charset.CharsetTest#test_x_UTF_16LE_BOM",
- "libcore.java.nio.charset.CharsetTest#test_X_UTF_32BE_BOM",
- "libcore.java.nio.charset.CharsetTest#test_X_UTF_32LE_BOM",
- "libcore.java.nio.charset.OldCharset_MultiByte_UTF_16#test_Encode"
+ "libcore.java.nio.charset.OldCharset_MultiByte_UTF_16#test_Encode",
+ "tests.api.java.nio.charset.CharsetTest#test_UTF_16",
+ "tests.api.java.nio.charset.CharsetTest#test_UTF_32",
+ "tests.api.java.nio.charset.CharsetTest#test_UTF_16BE",
+ "tests.api.java.nio.charset.CharsetTest#test_UTF_16LE",
+ "tests.api.java.nio.charset.CharsetTest#test_UTF_32BE",
+ "tests.api.java.nio.charset.CharsetTest#test_UTF_32LE",
+ "tests.api.java.nio.charset.CharsetTest#test_x_UTF_16LE_BOM",
+ "tests.api.java.nio.charset.CharsetTest#test_X_UTF_32BE_BOM",
+ "tests.api.java.nio.charset.CharsetTest#test_X_UTF_32LE_BOM"
],
bug: 2702411
},
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java
index 459bce1..b3e1abc 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java
@@ -4,9 +4,9 @@
* The ASF licenses this file to You 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.
@@ -15,15 +15,21 @@
*/
package org.apache.harmony.luni.tests.java.util;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.StringReader;
@@ -33,10 +39,12 @@
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
-import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
+import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
+import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
@@ -44,9 +52,9 @@
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
-import java.util.Scanner;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
+import java.util.Scanner;
import junit.framework.TestCase;
@@ -88,24 +96,24 @@
try {
s = new Scanner(tmpFile);
- fail("should throw FileNotFoundException");
- } catch (FileNotFoundException e) {
- // expected
+ fail();
+ } catch (FileNotFoundException expected) {
}
tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
FileOutputStream fos = new FileOutputStream(tmpFile);
fos.write("test".getBytes());
+ fos.close();
s = new Scanner(tmpFile);
+ s.close();
tmpFile.delete();
// Scanner(File = null)
try {
s = new Scanner((File) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// TODO: test if the default charset is used.
@@ -124,24 +132,21 @@
try {
s = new Scanner(tmpFile, Charset.defaultCharset().name());
- fail("should throw FileNotFoundException");
- } catch (FileNotFoundException e) {
- // expected
+ fail();
+ } catch (FileNotFoundException expected) {
}
try {
s = new Scanner(tmpFile, null);
- fail("should throw FileNotFoundException");
- } catch (FileNotFoundException e) {
- // expected
+ fail();
+ } catch (FileNotFoundException expected) {
}
tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
try {
s = new Scanner(tmpFile, "invalid charset");
- fail("should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
//fail on RI. File is opened but not closed when exception is thrown on
@@ -151,34 +156,30 @@
// Scanner(File = null, Charset = null)
try {
s = new Scanner((File) null, null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// Scanner(File = null, Charset = UTF-8)
try {
s = new Scanner((File) null, "UTF-8");
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// Scanner(File = null, Charset = invalid)
try {
s = new Scanner((File) null, "invalid");
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// Scanner(File, Charset = null)
try {
File f = File.createTempFile("test", ".tmp");
s = new Scanner(f, null);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
// TODO: test if the specified charset is used.
@@ -195,9 +196,8 @@
// Scanner(InputStream)
try {
s = new Scanner((InputStream) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// TODO: test if the default charset is used.
@@ -213,23 +213,20 @@
try {
s = new Scanner((PipedInputStream) null, "invalid charset");
- fail("should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
try {
s = new Scanner(new PipedInputStream(), null);
- fail("should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
try {
s = new Scanner(new PipedInputStream(), "invalid charset");
- fail("should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
// TODO: test if the specified charset is used.
@@ -246,9 +243,8 @@
// Scanner(Readable)
try {
s = new Scanner((Readable) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
}
@@ -267,9 +263,8 @@
// Scanner(ReadableByteChannel)
try {
s = new Scanner((ReadableByteChannel) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// Test if the default charset is used.
@@ -307,9 +302,8 @@
fc = new FileOutputStream(tmpFile).getChannel();
try {
s = new Scanner(fc, "invalid charset");
- fail("should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
fc.close();
assertTrue(tmpFile.delete());
@@ -317,29 +311,49 @@
// Scanner(ReadableByteChannel = null, Charset = null)
try {
s = new Scanner((ReadableByteChannel) null, null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// Scanner(ReadableByteChannel = null, Charset = invalid)
try {
s = new Scanner((ReadableByteChannel) null, "invalid");
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
// Scanner(ReadableByteChannel, Charset = null)
try {
s = new Scanner(fc, null);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
// TODO: test if the specified charset is used.
}
+ public void test_Constructor_LReadableByteChannel() throws IOException {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(null);
+
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(ssc.socket().getLocalSocketAddress());
+ sc.configureBlocking(false);
+ assertFalse(sc.isBlocking());
+
+ ssc.accept().close();
+ ssc.close();
+ assertFalse(sc.isBlocking());
+
+ Scanner s = new Scanner(sc);
+ try {
+ s.hasNextInt();
+ fail();
+ } catch (IllegalBlockingModeException expected) {
+ }
+
+ sc.close();
+ }
+
/**
* @tests java.util.Scanner#Scanner(String)
*/
@@ -351,9 +365,8 @@
// Scanner(String)
try {
s = new Scanner((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
}
@@ -376,9 +389,8 @@
// thrown out.
try {
fos.write(12);
- fail("Should throw IOException");
- } catch (IOException e) {
- // expected
+ fail();
+ } catch (IOException expected) {
}
s.close(); // no exception should be thrown
@@ -427,9 +439,8 @@
s = new Scanner("test");
try {
s.useDelimiter((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
s = new Scanner("test");
@@ -452,9 +463,8 @@
s = new Scanner("test");
try {
s.useLocale(null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
s.useLocale(new Locale("test", "test"));
@@ -476,15 +486,13 @@
s = new Scanner("test");
try {
s.useRadix(Character.MIN_RADIX - 1);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
try {
s.useRadix(Character.MAX_RADIX + 1);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
s.useRadix(11);
assertEquals(11, s.radix());
@@ -497,9 +505,8 @@
s = new Scanner("aab*b*").useDelimiter("\\*");
try {
s.remove();
- fail("should throw UnsupportedOperationException");
- } catch (UnsupportedOperationException e) {
- //Expected
+ fail();
+ } catch (UnsupportedOperationException expected) {
}
}
@@ -511,9 +518,8 @@
s = new Scanner("1 2 ");
try {
s.match();
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
+ fail();
+ } catch (IllegalStateException expected) {
}
assertEquals("1", s.next());
assertEquals("2", s.next());
@@ -527,29 +533,25 @@
assertEquals(0, result.groupCount());
try {
result.start(1);
- fail("should throw IndexOutOfBoundsException");
- } catch (IndexOutOfBoundsException e) {
- // Expected
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
}
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
try {
s.match();
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
+ fail();
+ } catch (IllegalStateException expected) {
}
-
+
s = new Scanner("True faLse");
try {
s.match();
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
+ fail();
+ } catch (IllegalStateException expected) {
}
assertTrue(s.nextBoolean());
result = s.match();
@@ -562,17 +564,15 @@
assertFalse(s.nextBoolean());
try {
s.nextBoolean();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
try {
s.match();
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
+ fail();
+ } catch (IllegalStateException expected) {
}
-
+
s = new Scanner("True faLse");
assertTrue(s.nextBoolean());
result = s.match();
@@ -585,9 +585,8 @@
s.close();
try {
s.nextBoolean();
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
+ fail();
+ } catch (IllegalStateException expected) {
}
result = s.match();
assertEquals(0, result.start());
@@ -596,30 +595,27 @@
assertEquals(4, result.end(0));
assertEquals("True", result.group());
assertEquals(0, result.groupCount());
-
+
s = new Scanner("True fase");
assertTrue(s.nextBoolean());
assertEquals(0, result.groupCount());
try {
s.nextBoolean();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
try {
s.match();
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
+ fail();
+ } catch (IllegalStateException expected) {
}
-
+
s = new Scanner("True fase");
assertTrue(s.nextBoolean());
try {
s.next((Pattern)null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // Expected
+ fail();
+ } catch (NullPointerException expected) {
}
result = s.match();
assertEquals(0, result.start());
@@ -628,9 +624,9 @@
assertEquals(4, result.end(0));
assertEquals("True", result.group());
assertEquals(0, result.groupCount());
-
+
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#next()
@@ -647,28 +643,25 @@
assertEquals("2", s.next());
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
-
+
s = new Scanner("a").useDelimiter("a?");
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
-
+
s = new Scanner("aa").useDelimiter("a?");
assertEquals("", s.next());
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
-
+
s = new Scanner("word( )test( )").useDelimiter("\\( \\)");
assertEquals("word", s.next());
@@ -685,27 +678,24 @@
// test boundary case
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// just delimiter exists in this scanner
s = new Scanner(" ");
try {
s.next();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// nothing exists in this scanner
s = new Scanner("");
try {
s.next();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// no delimiter exists in this scanner
@@ -741,23 +731,21 @@
Pattern.MULTILINE));
assertEquals("test\n", s.next());
assertEquals("test", s.next());
-
+
s = new Scanner("").useDelimiter(Pattern.compile("^",
Pattern.MULTILINE));
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
-
+
s = new Scanner("").useDelimiter(Pattern.compile("^*",
Pattern.MULTILINE));
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("test\ntest").useDelimiter(Pattern.compile("^*",
@@ -786,13 +774,12 @@
assertEquals("2", s.next());
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#next(Pattern)
@@ -804,9 +791,8 @@
assertEquals("aab", s.next(pattern));
try {
s.next(pattern);
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("word ? ");
@@ -814,9 +800,8 @@
assertEquals("word", s.next(pattern));
try {
s.next(pattern);
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("word1 word2 ");
@@ -826,9 +811,8 @@
// test boundary case
try {
s.next(pattern);
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// test socket inputStream
@@ -841,9 +825,8 @@
assertEquals("aab", s.next(pattern));
try {
s.next(pattern);
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
}
@@ -856,18 +839,16 @@
assertEquals("b", s.next("a*b"));
try {
s.next("a*b");
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("word ? ");
assertEquals("word", s.next("\\w+"));
try {
s.next("\\w+");
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("word1 next ");
@@ -876,9 +857,8 @@
// test boundary case
try {
s.next("\\w+");
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// test socket inputStream
@@ -889,12 +869,11 @@
assertEquals("aab", s.next("a*b"));
try {
s.next("a*b");
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextBoolean()
@@ -909,25 +888,22 @@
assertFalse(s.nextBoolean());
try {
s.nextBoolean();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("true1");
try {
s.nextBoolean();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
try {
s = new Scanner("");
s.nextBoolean();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// test socket inputStream
@@ -943,16 +919,15 @@
assertTrue(s.nextBoolean());
try {
s.nextBoolean();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("false( )").useDelimiter("\\( \\)");
assertFalse(s.nextBoolean());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextInt(int)
@@ -963,9 +938,8 @@
assertEquals(456, s.nextInt(10));
try {
s.nextInt(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -973,18 +947,16 @@
assertEquals(38, s.nextInt(5));
try {
s.nextInt(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("123456789123456789123456789123456789");
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -995,9 +967,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -1011,9 +982,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -1027,9 +997,8 @@
assertEquals(102, s.nextInt(10));
try {
s.nextInt(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertEquals(162, s.nextInt(10));
@@ -1041,9 +1010,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -1055,9 +1023,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -1086,7 +1053,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextInt(10));
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextInt(10));
@@ -1094,7 +1061,7 @@
/*
* There are three types of negative prefix all in all. '' '-' '(' There
* are three types of negative suffix all in all. '' '-' ')' '(' and ')'
- * must be used togethor. Prefix '-' and suffix '-' must be used
+ * must be used togethor. Prefix '-' and suffix '-' must be used
* exclusively.
*/
@@ -1112,9 +1079,8 @@
assertEquals(-123, s.nextInt(10));
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("-123 123-");
@@ -1122,9 +1088,8 @@
assertEquals(-123, s.nextInt(10));
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Skip the un-recognizable token 123-.
assertEquals("123-", s.next());
@@ -1133,15 +1098,13 @@
// RI
try {
s.nextInt(Character.MIN_RADIX - 1);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // Expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
try {
s.nextInt(Character.MAX_RADIX + 1);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // Expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
}
@@ -1155,9 +1118,8 @@
assertEquals(456, s.nextInt());
try {
s.nextInt();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -1166,18 +1128,16 @@
assertEquals(38, s.nextInt());
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("123456789123456789123456789123456789");
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -1188,9 +1148,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -1204,9 +1163,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -1221,9 +1179,8 @@
s.useRadix(5);
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertEquals(162, s.nextInt());
@@ -1236,9 +1193,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -1250,9 +1206,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -1284,7 +1239,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextInt());
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextInt());
@@ -1310,9 +1265,8 @@
assertEquals(-123, s.nextInt());
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("-123 123-");
@@ -1320,14 +1274,13 @@
assertEquals(-123, s.nextInt());
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Skip the un-recognizable token 123-.
assertEquals("123-", s.next());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextByte(int)
@@ -1338,9 +1291,8 @@
assertEquals(126, s.nextByte(10));
try {
s.nextByte(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -1348,18 +1300,16 @@
assertEquals(38, s.nextByte(5));
try {
s.nextByte(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("1234");
try {
s.nextByte(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -1369,9 +1319,8 @@
assertEquals(102, s.nextByte(10));
try {
s.nextByte(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertEquals(126, s.nextByte(10));
@@ -1392,7 +1341,7 @@
s = new Scanner("1\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(100, s.nextByte(10));
-
+
s = new Scanner("1\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(100, s.nextByte(10));
@@ -1400,7 +1349,7 @@
s = new Scanner("-123");
s.useLocale(new Locale("ar", "AE"));
assertEquals(-123, s.nextByte(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
@@ -1417,9 +1366,8 @@
assertEquals(126, s.nextByte());
try {
s.nextByte();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -1428,18 +1376,16 @@
assertEquals(38, s.nextByte());
try {
s.nextByte();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("1234");
try {
s.nextByte();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -1450,9 +1396,8 @@
s.useRadix(5);
try {
s.nextByte();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertEquals(126, s.nextByte());
@@ -1475,7 +1420,7 @@
s = new Scanner("1\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(100, s.nextByte());
-
+
s = new Scanner("1\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(100, s.nextByte());
@@ -1488,7 +1433,7 @@
s.useLocale(new Locale("mk", "MK"));
assertEquals(-123, s.nextByte());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextFloat()
@@ -1502,9 +1447,8 @@
assertEquals((float)0.123, s.nextFloat());
try {
s.nextFloat();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
@@ -1514,9 +1458,8 @@
assertEquals((float)123456.789, s.nextFloat());
try {
s.nextFloat();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Scientific notation
@@ -1534,7 +1477,7 @@
String str=String.valueOf(Float.MAX_VALUE*2);
s=new Scanner(str);
assertEquals(Float.POSITIVE_INFINITY,s.nextFloat());
-
+
/*
* Different locale can only recognize corresponding locale sensitive
* string. ',' is used in many locales as group separator.
@@ -1565,25 +1508,23 @@
// assertEquals((float)-123.4, s.nextFloat());
try {
s.nextFloat();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("123- -123");
s.useLocale(new Locale("mk", "MK"));
try {
s.nextFloat();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Skip the un-recognizable token 123-.
assertEquals("123-", s.next());
assertEquals((float)-123.0, s.nextFloat());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextBigInteger(int)
@@ -1594,9 +1535,8 @@
assertEquals(new BigInteger("456"), s.nextBigInteger(10));
try {
s.nextBigInteger(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -1604,9 +1544,8 @@
assertEquals(new BigInteger("38"), s.nextBigInteger(5));
try {
s.nextBigInteger(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -1617,9 +1556,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -1633,9 +1571,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -1649,9 +1586,8 @@
assertEquals(new BigInteger("102"), s.nextBigInteger(10));
try {
s.nextBigInteger(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertEquals(new BigInteger("162"), s.nextBigInteger(10));
@@ -1663,9 +1599,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -1677,9 +1612,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -1703,7 +1637,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
@@ -1711,7 +1645,7 @@
s = new Scanner("-123");
s.useLocale(new Locale("ar", "AE"));
assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
@@ -1728,9 +1662,8 @@
assertEquals(new BigInteger("456"), s.nextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -1739,9 +1672,8 @@
assertEquals(new BigInteger("38"), s.nextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -1752,9 +1684,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -1768,9 +1699,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -1785,9 +1715,8 @@
s.useRadix(5);
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertEquals(new BigInteger("162"), s.nextBigInteger());
@@ -1800,9 +1729,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -1814,9 +1742,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -1841,7 +1768,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(new BigInteger("12300"), s.nextBigInteger());
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(new BigInteger("12300"), s.nextBigInteger());
@@ -1854,7 +1781,7 @@
s.useLocale(new Locale("mk", "MK"));
assertEquals(new BigInteger("-123"), s.nextBigInteger());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextShort(int)
@@ -1865,9 +1792,8 @@
assertEquals(456, s.nextShort(10));
try {
s.nextShort(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -1875,18 +1801,16 @@
assertEquals(38, s.nextShort(5));
try {
s.nextShort(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("123456789");
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -1897,9 +1821,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -1913,9 +1836,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -1929,9 +1851,8 @@
assertEquals(102, s.nextShort(10));
try {
s.nextShort(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertEquals(162, s.nextShort(10));
@@ -1943,9 +1864,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -1957,9 +1877,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -1983,7 +1902,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextShort(10));
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextShort(10));
@@ -1991,7 +1910,7 @@
s = new Scanner("-123");
s.useLocale(new Locale("ar", "AE"));
assertEquals(-123, s.nextShort(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
@@ -2008,9 +1927,8 @@
assertEquals(456, s.nextShort());
try {
s.nextShort();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -2019,18 +1937,16 @@
assertEquals(38, s.nextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("123456789");
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -2041,9 +1957,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -2057,9 +1972,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -2074,9 +1988,8 @@
s.useRadix(5);
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertEquals(162, s.nextShort());
@@ -2089,9 +2002,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -2103,9 +2015,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -2130,7 +2041,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextShort());
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextShort());
@@ -2143,7 +2054,7 @@
s.useLocale(new Locale("mk", "MK"));
assertEquals(-123, s.nextShort());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextLong(int)
@@ -2154,9 +2065,8 @@
assertEquals(456, s.nextLong(10));
try {
s.nextLong(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -2164,18 +2074,16 @@
assertEquals(38, s.nextLong(5));
try {
s.nextLong(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("123456789123456789123456789123456789");
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -2186,9 +2094,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -2202,9 +2109,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -2218,9 +2124,8 @@
assertEquals(102, s.nextLong(10));
try {
s.nextLong(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertEquals(162, s.nextLong(10));
@@ -2232,9 +2137,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -2246,9 +2150,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -2272,7 +2175,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextLong(10));
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextLong(10));
@@ -2280,13 +2183,13 @@
s = new Scanner("-123");
s.useLocale(new Locale("ar", "AE"));
assertEquals(-123, s.nextLong(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
assertEquals(-123, s.nextLong(10));
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextLong()
@@ -2297,9 +2200,8 @@
assertEquals(456, s.nextLong());
try {
s.nextLong();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -2308,18 +2210,16 @@
assertEquals(38, s.nextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
s = new Scanner("123456789123456789123456789123456789");
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -2330,9 +2230,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -2346,9 +2245,8 @@
s.useLocale(Locale.GERMANY);
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -2363,9 +2261,8 @@
s.useRadix(5);
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertEquals(162, s.nextLong());
@@ -2378,9 +2275,8 @@
s.useLocale(Locale.CHINESE);
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -2392,9 +2288,8 @@
s.useLocale(Locale.ENGLISH);
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -2419,7 +2314,7 @@
s = new Scanner("123\u0966\u0966");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextLong());
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertEquals(12300, s.nextLong());
@@ -2432,7 +2327,7 @@
s.useLocale(new Locale("mk", "MK"));
assertEquals(-123, s.nextLong());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNext()
@@ -2447,9 +2342,8 @@
s.close();
try {
s.hasNext();
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("1( )2( )").useDelimiter("\\( \\)");
@@ -2472,9 +2366,8 @@
// test boundary case
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("1'\n'2 ");
@@ -2485,9 +2378,8 @@
// test boundary case
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner(" ");
@@ -2505,12 +2397,11 @@
assertFalse(s.hasNext());
try {
s.next();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNext(Pattern)
@@ -2524,9 +2415,8 @@
assertFalse(s.hasNext(pattern));
try {
s.next(pattern);
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("word ? ");
@@ -2536,9 +2426,8 @@
assertFalse(s.hasNext(pattern));
try {
s.next(pattern);
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("word1 WorD2 ");
@@ -2550,27 +2439,24 @@
assertFalse(s.hasNext(pattern));
try {
s.next(pattern);
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("word1 WorD2 ");
pattern = Pattern.compile("\\w+");
try {
s.hasNext((Pattern) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
s.close();
try {
s.hasNext(pattern);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
-
+
// test socket inputStream
os.write("aab b".getBytes());
serverSocket.close();
@@ -2582,12 +2468,11 @@
assertFalse(s.hasNext(pattern));
try {
s.next(pattern);
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNext(String)
@@ -2596,27 +2481,24 @@
s = new Scanner("aab@2@abb@").useDelimiter("\\@");
try {
s.hasNext((String)null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
-
+
s = new Scanner("aab*b*").useDelimiter("\\*");
assertTrue(s.hasNext("a+b"));
assertEquals("aab", s.next("a+b"));
assertFalse(s.hasNext("a+b"));
try {
s.next("a+b");
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.close();
try {
s.hasNext("a+b");
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("WORD ? ");
@@ -2625,9 +2507,8 @@
assertFalse(s.hasNext("\\w+"));
try {
s.next("\\w+");
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("word1 word2 ");
@@ -2636,9 +2517,8 @@
// test boundary case
try {
s.next("\\w+");
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// test socket inputStream
@@ -2652,12 +2532,11 @@
assertFalse(s.hasNext("a*b"));
try {
s.next("a*b");
- fail("should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextBoolean()
@@ -2693,9 +2572,8 @@
assertFalse(s.hasNextBoolean());
try {
s.nextBoolean();
- fail("should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("false( )").useDelimiter("\\( \\)");
@@ -2704,7 +2582,7 @@
assertFalse(s.hasNextBoolean());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextByte(int)
@@ -2718,9 +2596,8 @@
assertFalse(s.hasNextByte(10));
try {
s.nextByte(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -2730,9 +2607,8 @@
assertFalse(s.hasNextByte(5));
try {
s.nextByte(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -2740,9 +2616,8 @@
assertFalse(s.hasNextByte(10));
try {
s.nextByte(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -2754,9 +2629,8 @@
assertFalse(s.hasNextByte(5));
try {
s.nextByte(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertTrue(s.hasNextByte(10));
assertEquals(126, s.nextByte(10));
@@ -2782,7 +2656,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextByte(10));
assertEquals(100, s.nextByte(10));
-
+
s = new Scanner("1\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextByte(10));
@@ -2792,7 +2666,7 @@
s.useLocale(new Locale("ar", "AE"));
assertTrue(s.hasNextByte(10));
assertEquals(-123, s.nextByte(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
@@ -2800,42 +2674,34 @@
assertEquals(-123, s.nextByte(10));
}
- /**
- * @throws IOException
- * @tests java.util.Scanner#hasNextByte(int)
- */
public void test_hasNextByteI_cache() throws IOException{
//regression for HARMONY-2063
- s = new Scanner("123 45");
- assertTrue(s.hasNextByte(8));
- assertEquals(83, s.nextByte());
- assertEquals(45, s.nextByte());
+ s = new Scanner("123 45");
+ assertTrue(s.hasNextByte(8));
+ assertEquals(83, s.nextByte());
+ assertEquals(45, s.nextByte());
- s = new Scanner("123 45");
- assertTrue(s.hasNextByte(10));
- assertTrue(s.hasNextByte(8));
- assertEquals(83, s.nextByte());
- assertEquals(45, s.nextByte());
+ s = new Scanner("123 45");
+ assertTrue(s.hasNextByte(10));
+ assertTrue(s.hasNextByte(8));
+ assertEquals(83, s.nextByte());
+ assertEquals(45, s.nextByte());
- s = new Scanner("-123 -45");
- assertTrue(s.hasNextByte(8));
- assertEquals(-123, s.nextInt());
- assertEquals(-45, s.nextByte());
-
- s = new Scanner("123 45");
- assertTrue(s.hasNextByte());
- s.close();
- try {
- s.nextByte();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
+ s = new Scanner("-123 -45");
+ assertTrue(s.hasNextByte(8));
+ assertEquals(-123, s.nextInt());
+ assertEquals(-45, s.nextByte());
+
+ s = new Scanner("123 45");
+ assertTrue(s.hasNextByte());
+ s.close();
+ try {
+ s.nextByte();
+ fail();
+ } catch (IllegalStateException expected) {
+ }
}
- /**
- * @throws IOException
- * @tests java.util.Scanner#hasNextByte()
- */
+
public void test_hasNextByte() throws IOException {
s = new Scanner("123 126");
assertTrue(s.hasNextByte());
@@ -2845,9 +2711,8 @@
assertFalse(s.hasNextByte());
try {
s.nextByte();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -2858,9 +2723,8 @@
assertFalse(s.hasNextByte());
try {
s.nextByte();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -2868,9 +2732,8 @@
assertFalse(s.hasNextByte());
try {
s.nextByte();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -2883,9 +2746,8 @@
assertFalse(s.hasNextByte());
try {
s.nextByte();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertTrue(s.hasNextByte());
@@ -2912,7 +2774,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextByte());
assertEquals(100, s.nextByte());
-
+
s = new Scanner("1\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextByte());
@@ -2928,7 +2790,7 @@
assertTrue(s.hasNextByte());
assertEquals(-123, s.nextByte());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextBigInteger(int)
@@ -2942,9 +2804,8 @@
assertFalse(s.hasNextBigInteger(10));
try {
s.nextBigInteger(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -2954,9 +2815,8 @@
assertFalse(s.hasNextBigInteger(5));
try {
s.nextBigInteger(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -2968,9 +2828,8 @@
assertFalse(s.hasNextBigInteger(10));
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -2987,9 +2846,8 @@
assertFalse(s.hasNextBigInteger(10));
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -3007,9 +2865,8 @@
assertFalse(s.hasNextBigInteger(5));
try {
s.nextBigInteger(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertTrue(s.hasNextBigInteger(10));
assertEquals(new BigInteger("162"), s.nextBigInteger(10));
@@ -3023,9 +2880,8 @@
assertFalse(s.hasNextBigInteger(10));
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -3040,9 +2896,8 @@
assertFalse(s.hasNextBigInteger(10));
try {
s.nextBigInteger(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -3071,7 +2926,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextBigInteger(10));
assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextBigInteger(10));
@@ -3081,47 +2936,46 @@
s.useLocale(new Locale("ar", "AE"));
assertTrue(s.hasNextBigInteger(10));
assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
assertTrue(s.hasNextBigInteger(10));
assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextBigInteger(int)
*/
public void test_hasNextBigIntegerI_cache() throws IOException {
//regression for HARMONY-2063
- s = new Scanner("123 123456789123456789");
- assertTrue(s.hasNextBigInteger(16));
- assertEquals(new BigInteger("291"), s.nextBigInteger());
- assertEquals(new BigInteger("123456789123456789"), s.nextBigInteger());
+ s = new Scanner("123 123456789123456789");
+ assertTrue(s.hasNextBigInteger(16));
+ assertEquals(new BigInteger("291"), s.nextBigInteger());
+ assertEquals(new BigInteger("123456789123456789"), s.nextBigInteger());
- s = new Scanner("123456789123456789 456");
- assertTrue(s.hasNextBigInteger(16));
- assertTrue(s.hasNextBigInteger(10));
- assertEquals(new BigInteger("123456789123456789"), s.nextBigInteger());
- assertEquals(new BigInteger("456"), s.nextBigInteger());
+ s = new Scanner("123456789123456789 456");
+ assertTrue(s.hasNextBigInteger(16));
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("123456789123456789"), s.nextBigInteger());
+ assertEquals(new BigInteger("456"), s.nextBigInteger());
- s = new Scanner("-123 -123456789123456789");
- assertTrue(s.hasNextBigInteger(8));
- assertEquals(-123, s.nextShort());
- assertEquals(new BigInteger("-123456789123456789"), s.nextBigInteger());
-
- s = new Scanner("123 456");
- assertTrue(s.hasNextBigInteger());
- s.close();
- try {
- s.nextBigInteger();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
+ s = new Scanner("-123 -123456789123456789");
+ assertTrue(s.hasNextBigInteger(8));
+ assertEquals(-123, s.nextShort());
+ assertEquals(new BigInteger("-123456789123456789"), s.nextBigInteger());
+
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextBigInteger());
+ s.close();
+ try {
+ s.nextBigInteger();
+ fail();
+ } catch (IllegalStateException expected) {
+ }
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextBigInteger()
@@ -3135,9 +2989,8 @@
assertFalse(s.hasNextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -3148,9 +3001,8 @@
assertFalse(s.hasNextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -3162,9 +3014,8 @@
assertFalse(s.hasNextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -3181,9 +3032,8 @@
assertFalse(s.hasNextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -3201,9 +3051,8 @@
assertFalse(s.hasNextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertTrue(s.hasNextBigInteger());
@@ -3218,9 +3067,8 @@
assertFalse(s.hasNextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -3235,9 +3083,8 @@
assertFalse(s.hasNextBigInteger());
try {
s.nextBigInteger();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -3267,7 +3114,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextBigInteger());
assertEquals(new BigInteger("12300"), s.nextBigInteger());
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextBigInteger());
@@ -3283,7 +3130,7 @@
assertTrue(s.hasNextBigInteger());
assertEquals(new BigInteger("-123"), s.nextBigInteger());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextInt(int)
@@ -3296,9 +3143,8 @@
assertFalse(s.hasNextInt(10));
try {
s.nextInt(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -3308,9 +3154,8 @@
assertFalse(s.hasNextInt(5));
try {
s.nextInt(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -3353,9 +3198,8 @@
assertFalse(s.hasNextInt(10));
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
assertTrue(s.hasNextInt(10));
@@ -3366,9 +3210,8 @@
assertFalse(s.hasNextInt(10));
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -3393,9 +3236,8 @@
// If parameter radix is illegal, the following test case fails on RI
try {
s.hasNextInt(Character.MIN_RADIX - 1);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // Expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
/*
@@ -3420,7 +3262,7 @@
/*
* There are three types of negative prefix all in all. '' '-' '(' There
* are three types of negative suffix all in all. '' '-' ')' '(' and ')'
- * must be used togethor. Prefix '-' and suffix '-' must be used
+ * must be used together. Prefix '-' and suffix '-' must be used
* exclusively.
*/
@@ -3428,7 +3270,7 @@
* According to Integer regular expression: Integer :: = ( [-+]? (*
* Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
* LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
- * recognized by scanner with locale ar_AE, (123) shouble be recognized
+ * recognized by scanner with locale ar_AE, (123) should be recognized
* by scanner with locale mk_MK. But this is not the case on RI.
*/
s = new Scanner("-123 123- -123-");
@@ -3441,9 +3283,8 @@
assertFalse(s.hasNextInt(10));
try {
s.nextInt(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("-123 123-");
@@ -3453,9 +3294,8 @@
assertFalse(s.hasNextInt(10));
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Skip the un-recognizable token 123-.
assertEquals("123-", s.next());
@@ -3467,33 +3307,32 @@
*/
public void test_hasNextIntI_cache() throws IOException {
//regression for HARMONY-2063
- s = new Scanner("123 456");
- assertTrue(s.hasNextInt(16));
- assertEquals(291, s.nextInt(10));
- assertEquals(456, s.nextInt());
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextInt(16));
+ assertEquals(291, s.nextInt(10));
+ assertEquals(456, s.nextInt());
- s = new Scanner("123 456");
- assertTrue(s.hasNextInt(16));
- assertTrue(s.hasNextInt(8));
- assertEquals(83, s.nextInt());
- assertEquals(456, s.nextInt());
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextInt(16));
+ assertTrue(s.hasNextInt(8));
+ assertEquals(83, s.nextInt());
+ assertEquals(456, s.nextInt());
- s = new Scanner("-123 -456 -789");
- assertTrue(s.hasNextInt(8));
- assertEquals(-123, s.nextShort());
- assertEquals(-456, s.nextInt());
- assertTrue(s.hasNextShort(16));
- assertEquals(-789, s.nextInt());
-
- s = new Scanner("123 456");
- assertTrue(s.hasNextInt());
- s.close();
- try {
- s.nextInt();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
+ s = new Scanner("-123 -456 -789");
+ assertTrue(s.hasNextInt(8));
+ assertEquals(-123, s.nextShort());
+ assertEquals(-456, s.nextInt());
+ assertTrue(s.hasNextShort(16));
+ assertEquals(-789, s.nextInt());
+
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextInt());
+ s.close();
+ try {
+ s.nextInt();
+ fail();
+ } catch (IllegalStateException expected) {
+ }
}
/**
* @throws IOException
@@ -3507,9 +3346,8 @@
assertFalse(s.hasNextInt());
try {
s.nextInt();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -3520,9 +3358,8 @@
assertFalse(s.hasNextInt());
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -3571,9 +3408,8 @@
assertFalse(s.hasNextInt());
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -3619,7 +3455,7 @@
/*
* There are three types of negative prefix all in all. '' '-' '(' There
* are three types of negative suffix all in all. '' '-' ')' '(' and ')'
- * must be used togethor. Prefix '-' and suffix '-' must be used
+ * must be used togethor. Prefix '-' and suffix '-' must be used
* exclusively.
*/
@@ -3640,9 +3476,8 @@
assertFalse(s.hasNextInt());
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("-123 123-");
@@ -3651,14 +3486,13 @@
assertEquals(-123, s.nextInt());
try {
s.nextInt();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Skip the un-recognizable token 123-.
assertEquals("123-", s.next());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextFloat()
@@ -3677,9 +3511,8 @@
assertFalse(s.hasNextFloat());
try {
s.nextFloat();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
@@ -3693,9 +3526,8 @@
assertFalse(s.hasNextFloat());
try {
s.nextFloat();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Scientific notation
@@ -3720,7 +3552,7 @@
s=new Scanner(str);
assertTrue(s.hasNextFloat());
assertEquals(Float.POSITIVE_INFINITY,s.nextFloat());
-
+
/*
* Different locale can only recognize corresponding locale sensitive
* string. ',' is used in many locales as group separator.
@@ -3759,9 +3591,8 @@
// assertEquals((float)-123.4, s.nextFloat());
// try {
// s.nextFloat();
-// fail("Should throw InputMismatchException");
-// } catch (InputMismatchException e) {
-// // Expected
+// fail();
+// } catch (InputMismatchException expected) {
// }
s = new Scanner("123- -123");
@@ -3769,28 +3600,26 @@
assertFalse(s.hasNextFloat());
try {
s.nextFloat();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Skip the un-recognizable token 123-.
assertEquals("123-", s.next());
assertTrue(s.hasNextFloat());
assertEquals((float)-123.0, s.nextFloat());
-
+
s = new Scanner("+123.4 -456.7");
s.useLocale(Locale.ENGLISH);
assertTrue(s.hasNextFloat());
s.close();
try{
- s.nextFloat();
- fail("Should throw IllegalStateException");
- }catch(IllegalStateException e){
- //expected
+ s.nextFloat();
+ fail();
+ }catch(IllegalStateException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextShort(int)
@@ -3804,9 +3633,8 @@
assertFalse(s.hasNextShort(10));
try {
s.nextShort(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -3816,9 +3644,8 @@
assertFalse(s.hasNextShort(5));
try {
s.nextShort(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -3826,9 +3653,8 @@
assertFalse(s.hasNextShort(10));
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -3840,9 +3666,8 @@
assertFalse(s.hasNextShort(10));
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -3859,9 +3684,8 @@
assertFalse(s.hasNextShort(10));
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -3879,9 +3703,8 @@
assertFalse(s.hasNextShort(5));
try {
s.nextShort(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertTrue(s.hasNextShort(10));
assertEquals(162, s.nextShort(10));
@@ -3895,9 +3718,8 @@
assertFalse(s.hasNextShort(10));
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -3912,9 +3734,8 @@
assertFalse(s.hasNextShort(10));
try {
s.nextShort(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -3943,7 +3764,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextShort(10));
assertEquals(12300, s.nextShort(10));
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextShort(10));
@@ -3953,7 +3774,7 @@
s.useLocale(new Locale("ar", "AE"));
assertTrue(s.hasNextShort(10));
assertEquals(-123, s.nextShort(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
@@ -3974,9 +3795,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -3987,9 +3807,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -3997,9 +3816,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -4011,9 +3829,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -4030,9 +3847,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -4050,9 +3866,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertTrue(s.hasNextShort());
@@ -4067,9 +3882,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -4084,9 +3898,8 @@
assertFalse(s.hasNextShort());
try {
s.nextShort();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -4116,7 +3929,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextShort());
assertEquals(12300, s.nextShort());
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextShort());
@@ -4132,46 +3945,45 @@
assertTrue(s.hasNextShort());
assertEquals(-123, s.nextShort());
}
-
+
/**
- * @throws IOException
- * @tests java.util.Scanner#hasNextShort(int)
- */
- public void test_hasNextShortI_cache() throws IOException {
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextShort(int)
+ */
+ public void test_hasNextShortI_cache() throws IOException {
//regression for HARMONY-2063
- s = new Scanner("123 456");
- assertTrue(s.hasNextShort(16));
- assertEquals(291, s.nextShort());
- assertEquals(456, s.nextShort());
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextShort(16));
+ assertEquals(291, s.nextShort());
+ assertEquals(456, s.nextShort());
- s = new Scanner("123 456");
- assertTrue(s.hasNextShort(16));
- assertTrue(s.hasNextShort(8));
- assertEquals(83, s.nextShort());
- assertEquals(456, s.nextShort());
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextShort(16));
+ assertTrue(s.hasNextShort(8));
+ assertEquals(83, s.nextShort());
+ assertEquals(456, s.nextShort());
- s = new Scanner("-123 -456 -789");
- assertTrue(s.hasNextShort(8));
- assertEquals(-123, s.nextInt());
- assertEquals(-456, s.nextShort());
- assertTrue(s.hasNextInt(16));
- assertEquals(-789, s.nextShort());
-
- s = new Scanner("123 456");
- assertTrue(s.hasNextShort());
- s.close();
- try {
- s.nextShort();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
- }
-
+ s = new Scanner("-123 -456 -789");
+ assertTrue(s.hasNextShort(8));
+ assertEquals(-123, s.nextInt());
+ assertEquals(-456, s.nextShort());
+ assertTrue(s.hasNextInt(16));
+ assertEquals(-789, s.nextShort());
+
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextShort());
+ s.close();
+ try {
+ s.nextShort();
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ }
+
/**
- * @throws IOException
- * @tests java.util.Scanner#hasNextLong(int)
- */
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextLong(int)
+ */
public void test_hasNextLongI() throws IOException {
s = new Scanner("123 456");
assertTrue(s.hasNextLong(10));
@@ -4181,9 +3993,8 @@
assertFalse(s.hasNextLong(10));
try {
s.nextLong(10);
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -4193,9 +4004,8 @@
assertFalse(s.hasNextLong(5));
try {
s.nextLong(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -4203,9 +4013,8 @@
assertFalse(s.hasNextLong(10));
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -4217,9 +4026,8 @@
assertFalse(s.hasNextShort(10));
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -4236,9 +4044,8 @@
assertFalse(s.hasNextLong(10));
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -4256,9 +4063,8 @@
assertFalse(s.hasNextLong(5));
try {
s.nextLong(5);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
assertTrue(s.hasNextLong(10));
assertEquals(162, s.nextLong(10));
@@ -4272,9 +4078,8 @@
assertFalse(s.hasNextLong(10));
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -4289,9 +4094,8 @@
assertFalse(s.hasNextLong(10));
try {
s.nextLong(10);
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -4320,7 +4124,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextLong(10));
assertEquals(12300, s.nextLong(10));
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextLong(10));
@@ -4330,47 +4134,46 @@
s.useLocale(new Locale("ar", "AE"));
assertTrue(s.hasNextLong(10));
assertEquals(-123, s.nextLong(10));
-
+
s = new Scanner("-123");
s.useLocale(new Locale("mk", "MK"));
assertTrue(s.hasNextLong(10));
assertEquals(-123, s.nextLong(10));
}
-
+
/**
- * @throws IOException
- * @tests java.util.Scanner#hasNextLong(int)
- */
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextLong(int)
+ */
public void test_hasNextLongI_cache() throws IOException {
//regression for HARMONY-2063
- s = new Scanner("123 456");
- assertTrue(s.hasNextLong(16));
- assertEquals(291, s.nextLong());
- assertEquals(456, s.nextLong());
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextLong(16));
+ assertEquals(291, s.nextLong());
+ assertEquals(456, s.nextLong());
- s = new Scanner("123 456");
- assertTrue(s.hasNextLong(16));
- assertTrue(s.hasNextLong(8));
- assertEquals(83, s.nextLong());
- assertEquals(456, s.nextLong());
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextLong(16));
+ assertTrue(s.hasNextLong(8));
+ assertEquals(83, s.nextLong());
+ assertEquals(456, s.nextLong());
- s = new Scanner("-123 -456 -789");
- assertTrue(s.hasNextLong(8));
- assertEquals(-123, s.nextInt());
- assertEquals(-456, s.nextLong());
- assertTrue(s.hasNextShort(16));
- assertEquals(-789, s.nextLong());
-
- s = new Scanner("123 456");
- assertTrue(s.hasNextLong());
- s.close();
- try {
- s.nextLong();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
+ s = new Scanner("-123 -456 -789");
+ assertTrue(s.hasNextLong(8));
+ assertEquals(-123, s.nextInt());
+ assertEquals(-456, s.nextLong());
+ assertTrue(s.hasNextShort(16));
+ assertEquals(-789, s.nextLong());
+
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextLong());
+ s.close();
+ try {
+ s.nextLong();
+ fail();
+ } catch (IllegalStateException expected) {
+ }
}
/**
@@ -4386,9 +4189,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// If the radix is different from 10
@@ -4399,9 +4201,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// If the number is out of range
@@ -4409,9 +4210,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -4423,9 +4223,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.ENGLISH);
// If exception is thrown out, input will not be advanced.
@@ -4442,9 +4241,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(new Locale("it", "CH"));
// If exception is thrown out, input will not be advanced.
@@ -4462,9 +4260,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useRadix(10);
assertTrue(s.hasNextLong());
@@ -4479,9 +4276,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s.useLocale(Locale.GERMANY);
// If exception is thrown out, input will not be advanced.
@@ -4496,9 +4292,8 @@
assertFalse(s.hasNextLong());
try {
s.nextLong();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
s = new Scanner("03456");
@@ -4528,7 +4323,7 @@
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextLong());
assertEquals(12300, s.nextLong());
-
+
s = new Scanner("123\u0e50\u0e50");
s.useLocale(Locale.CHINESE);
assertTrue(s.hasNextLong());
@@ -4544,7 +4339,7 @@
assertTrue(s.hasNextLong());
assertEquals(-123, s.nextLong());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextDouble()
@@ -4563,9 +4358,8 @@
assertFalse(s.hasNextDouble());
try {
s.nextDouble();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
@@ -4579,9 +4373,8 @@
assertFalse(s.hasNextDouble());
try {
s.nextDouble();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Scientific notation
@@ -4606,7 +4399,7 @@
s=new Scanner(str);
assertTrue(s.hasNextDouble());
assertEquals(Double.POSITIVE_INFINITY,s.nextDouble());
-
+
/*
* Different locale can only recognize corresponding locale sensitive
* string. ',' is used in many locales as group separator.
@@ -4639,19 +4432,18 @@
s.useLocale(Locale.ENGLISH);
assertTrue(s.hasNextDouble());
assertEquals(-123.4, s.nextDouble());
-
+
s = new Scanner("+123.4 -456.7");
s.useLocale(Locale.ENGLISH);
assertTrue(s.hasNextDouble());
s.close();
try{
- s.nextDouble();
- fail("Should throw IllegalStateException");
- }catch(IllegalStateException e){
- //expected
+ s.nextDouble();
+ fail();
+ }catch(IllegalStateException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#hasNextBigDecimal()
@@ -4670,9 +4462,8 @@
assertFalse(s.hasNextBigDecimal());
try {
s.nextBigDecimal();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
@@ -4686,9 +4477,8 @@
assertFalse(s.hasNextBigDecimal());
try {
s.nextBigDecimal();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Scientific notation
@@ -4705,9 +4495,8 @@
assertFalse(s.hasNextBigDecimal());
try {
s.nextBigDecimal();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -4740,7 +4529,7 @@
assertTrue(s.hasNextBigDecimal());
assertEquals(new BigDecimal("-123.4"), s.nextBigDecimal());
}
-
+
private static class MockStringReader extends StringReader {
public MockStringReader(String param) {
@@ -4756,22 +4545,22 @@
}
}
-
+
private static class MockStringReader2Read extends StringReader {
- private int timesRead = 1;
+ int timesRead = 0;
public MockStringReader2Read(String param) {
super(param);
}
public int read(CharBuffer target) throws IOException {
- if (timesRead == 1) {
+ if (timesRead == 0) {
target.append('1');
target.append('2');
target.append('3');
timesRead++;
return 3;
- } else if (timesRead == 2) {
+ } else if (timesRead == 1) {
target.append('t');
timesRead++;
return 1;
@@ -4781,11 +4570,22 @@
}
}
-
+
+ // https://code.google.com/p/android/issues/detail?id=40555
+ public void test_40555() throws Exception {
+ MockStringReader2Read reader = new MockStringReader2Read("MockStringReader");
+ s = new Scanner(reader);
+ // We should get a match straight away.
+ String result = s.findWithinHorizon("1", 0);
+ assertEquals("1", result);
+ // The stream should not be consumed as there's already a match after the first read.
+ assertEquals(1, reader.timesRead);
+ }
+
/**
* @tests java.util.Scanner#findWithinHorizon(Pattern, int)
*/
- public void test_findWithinHorizon_LPatternI(){
+ public void test_findWithinHorizon_LPatternI() {
// This method searches through the input up to the specified search
// horizon(exclusive).
@@ -4823,9 +4623,8 @@
try {
s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
assertEquals("345", mresult.group());
assertEquals(2, mresult.start());
@@ -4853,24 +4652,21 @@
try {
s.findWithinHorizon((Pattern) null, -1);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
try {
s.findWithinHorizon(Pattern.compile("\\p{Digit}+"), -1);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
+ fail();
+ } catch (IllegalArgumentException expected) {
}
s.close();
try {
s.findWithinHorizon((Pattern) null, -1);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("test");
@@ -4878,22 +4674,19 @@
assertEquals("test", result);
s = new Scanner("aa\n\rb");
- String patternStr = "^(a)$";
result = s.findWithinHorizon(Pattern.compile("a"), 5);
assertEquals("a", result);
mresult = s.match();
assertEquals(0, mresult.start());
assertEquals(1, mresult.end());
- result = s.findWithinHorizon(Pattern.compile(patternStr,
- Pattern.MULTILINE), 5);
+ result = s.findWithinHorizon(Pattern.compile("^(a)$", Pattern.MULTILINE), 5);
assertNull(result);
try {
mresult = s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("");
@@ -4916,9 +4709,8 @@
try {
mresult = s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
assertEquals(0, mresult.groupCount());
@@ -4936,18 +4728,16 @@
s.close();
try {
s.findWithinHorizon(Pattern.compile("test"), 1);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("word1 WorD2 ");
s.close();
try {
s.findWithinHorizon(Pattern.compile("\\d+"), 10);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("word1 WorD2 wOrd3 ");
@@ -4970,6 +4760,7 @@
s = new Scanner(stringBuilder.toString());
pattern = Pattern.compile("\\p{Lower}+");
result = s.findWithinHorizon(pattern, 1026);
+ assertEquals(stringBuilder.toString().length(), result.length());
assertEquals(stringBuilder.toString(), result);
// Test the situation when input length is longer than buffer size and
@@ -5005,7 +4796,7 @@
pattern = Pattern.compile("\\p{Lower}+");
result = s.findWithinHorizon(pattern, 0);
assertEquals(stringBuilder.toString(), result);
-
+
stringBuilder = new StringBuilder();
for (int i = 0; i < 10240; i++) {
stringBuilder.append('-');
@@ -5014,12 +4805,12 @@
s = new Scanner(stringBuilder.toString());
result = s.findWithinHorizon(Pattern.compile("aa"), 0);
assertEquals("aa", result);
-
+
s = new Scanner("aaaa");
result = s.findWithinHorizon(Pattern.compile("a*"), 0);
assertEquals("aaaa", result);
}
-
+
/**
* @tests java.util.Scanner#findInLine(Pattern)
*/
@@ -5028,9 +4819,8 @@
Scanner s = new Scanner("");
try {
s.findInLine((Pattern) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // Expected
+ fail();
+ } catch (NullPointerException expected) {
}
String result = s.findInLine(Pattern.compile("^"));
assertEquals("", result);
@@ -5067,9 +4857,8 @@
assertNull(result);
try {
matchResult = s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
assertEquals(0, matchResult.start());
assertEquals(4, matchResult.end());
@@ -5096,9 +4885,8 @@
s.close();
try {
s.findInLine((Pattern) null);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("test1234\n1234 test");
@@ -5125,13 +4913,13 @@
matchResult = s.match();
assertEquals(14, matchResult.start());
assertEquals(18, matchResult.end());
-
+
s = new Scanner("test\u0085\ntest");
result = s.findInLine("est");
assertEquals("est", result);
result = s.findInLine("est");
assertEquals("est", result);
-
+
s = new Scanner("test\ntest");
result = s.findInLine("est");
assertEquals("est", result);
@@ -5144,39 +4932,134 @@
result = s.findInLine("est");
// RI fails. It is a RI's bug.
assertNull(result);
-
+
s = new Scanner( " *\n");
result = s.findInLine(Pattern.compile( "^\\s*(?:\\*(?=[^/]))"));
assertEquals(" *", result);
}
- /**
- * @tests java.util.Scanner#findInLine(String)
- */
- public void test_findInLine_LString() {
+ public void test_findInLine_LString_NPEs() {
s = new Scanner("test");
try {
s.findInLine((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
-
s.close();
try {
s.findInLine((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
try {
s.findInLine("test");
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // exptected
+ fail();
+ } catch (IllegalStateException expected) {
}
}
-
+
+ public void test_findInLine_LString() {
+ Scanner s = new Scanner("");
+ String result = s.findInLine("^");
+ assertEquals("", result);
+ MatchResult matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(0, matchResult.end());
+
+ result = s.findInLine("$");
+ assertEquals("", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(0, matchResult.end());
+
+ // When we use the operation of findInLine(Pattern), the match region
+ // should not span the line separator.
+ s = new Scanner("aa\nb.b");
+ result = s.findInLine("a\nb*");
+ assertNull(result);
+
+ s = new Scanner("aa\nbb.b");
+ result = s.findInLine("\\.");
+ assertNull(result);
+
+ s = new Scanner("abcd1234test\n");
+ result = s.findInLine("\\p{Lower}+");
+ assertEquals("abcd", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(4, matchResult.end());
+
+ result = s.findInLine("\\p{Digit}{5}");
+ assertNull(result);
+ try {
+ matchResult = s.match();
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ assertEquals(0, matchResult.start());
+ assertEquals(4, matchResult.end());
+
+ result = s.findInLine("\\p{Lower}+");
+ assertEquals("test", result);
+ matchResult = s.match();
+ assertEquals(8, matchResult.start());
+ assertEquals(12, matchResult.end());
+
+ char[] chars = new char[2048];
+ Arrays.fill(chars, 'a');
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append(chars);
+ stringBuilder.append("1234");
+ s = new Scanner(stringBuilder.toString());
+ result = s.findInLine("\\p{Digit}+");
+ assertEquals("1234", result);
+ matchResult = s.match();
+ assertEquals(2048, matchResult.start());
+ assertEquals(2052, matchResult.end());
+
+ s = new Scanner("test1234\n1234 test");
+ result = s.findInLine("test");
+ assertEquals("test", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(4, matchResult.end());
+
+ int number = s.nextInt();
+ assertEquals(1234, number);
+ matchResult = s.match();
+ assertEquals(4, matchResult.start());
+ assertEquals(8, matchResult.end());
+
+ result = s.next();
+ assertEquals("1234", result);
+ matchResult = s.match();
+ assertEquals(9, matchResult.start());
+ assertEquals(13, matchResult.end());
+
+ result = s.findInLine("test");
+ assertEquals("test", result);
+ matchResult = s.match();
+ assertEquals(14, matchResult.start());
+ assertEquals(18, matchResult.end());
+
+ s = new Scanner("test\u0085\ntest");
+ result = s.findInLine("est");
+ assertEquals("est", result);
+ result = s.findInLine("est");
+ assertEquals("est", result);
+
+ s = new Scanner("test\ntest");
+ result = s.findInLine("est");
+ assertEquals("est", result);
+ result = s.findInLine("est");
+ assertEquals("est", result);
+
+ s = new Scanner("test\n123\ntest");
+ result = s.findInLine("est");
+ assertEquals("est", result);
+ result = s.findInLine("est");
+ }
+
/**
* @tests java.util.Scanner#skip(Pattern)
*/
@@ -5184,25 +5067,22 @@
s = new Scanner("test");
try {
s.skip((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
-
+
// If pattern does not match, NoSuchElementException will be thrown out.
s = new Scanner("1234");
try {
s.skip(Pattern.compile("\\p{Lower}"));
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
// Then, no matchResult will be thrown out.
try {
s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s.skip(Pattern.compile("\\p{Digit}"));
@@ -5218,24 +5098,21 @@
s.close();
try {
s.skip(Pattern.compile("test"));
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
MockStringReader2Read reader = new MockStringReader2Read("test");
s = new Scanner(reader);
try {
s.skip(Pattern.compile("\\p{Digit}{4}"));
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
try {
s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s.skip(Pattern.compile("\\p{Digit}{3}\\p{Lower}"));
matchResult = s.match();
@@ -5245,11 +5122,10 @@
s.close();
try {
s.skip((Pattern) null);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
-
+
StringBuilder stringBuilder = new StringBuilder();
char [] chars = new char[1024];
Arrays.fill(chars, 'a');
@@ -5260,7 +5136,7 @@
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(1025, matchResult.end());
-
+
// Large amount of input may be cached
chars = new char[102400];
Arrays.fill(chars, 'a');
@@ -5271,7 +5147,7 @@
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(102400, matchResult.end());
-
+
// skip something without risking a NoSuchElementException
s.skip(Pattern.compile("[ \t]*"));
matchResult = s.match();
@@ -5286,12 +5162,11 @@
s = new Scanner("test");
try {
s.skip((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ fail();
+ } catch (NullPointerException expected) {
}
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextDouble()
@@ -5305,9 +5180,8 @@
assertEquals(0.123, s.nextDouble());
try {
s.nextDouble();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
@@ -5317,9 +5191,8 @@
assertEquals(123456.789, s.nextDouble());
try {
s.nextDouble();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Scientific notation
@@ -5333,7 +5206,7 @@
assertEquals(Double.NaN, s.nextDouble());
assertEquals(Double.POSITIVE_INFINITY, s.nextDouble());
assertEquals(Double.NEGATIVE_INFINITY, s.nextDouble());
-
+
//The following test case fails on RI
s=new Scanner("\u221e");
s.useLocale(Locale.ENGLISH);
@@ -5342,7 +5215,7 @@
String str=String.valueOf(Double.MAX_VALUE*2);
s=new Scanner(str);
assertEquals(Double.POSITIVE_INFINITY,s.nextDouble());
-
+
/*
* Different locale can only recognize corresponding locale sensitive
* string. ',' is used in many locales as group separator.
@@ -5369,7 +5242,7 @@
s.useLocale(Locale.ENGLISH);
assertEquals(-123.4, s.nextDouble());
}
-
+
/**
* @throws IOException
* @tests java.util.Scanner#nextBigDecimal()
@@ -5383,9 +5256,8 @@
assertEquals(new BigDecimal("0.123"), s.nextBigDecimal());
try {
s.nextBigDecimal();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
@@ -5395,9 +5267,8 @@
assertEquals(new BigDecimal("123456.789"), s.nextBigDecimal());
try {
s.nextBigDecimal();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
// Scientific notation
@@ -5410,9 +5281,8 @@
s = new Scanner("NaN");
try {
s.nextBigDecimal();
- fail("Should throw InputMismatchException");
- } catch (InputMismatchException e) {
- // Expected
+ fail();
+ } catch (InputMismatchException expected) {
}
/*
@@ -5456,11 +5326,10 @@
s.close();
try {
s.nextLine();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
-
+
s = new Scanner("test\r\ntest");
String result = s.nextLine();
assertEquals("test", result);
@@ -5474,33 +5343,31 @@
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(1, matchResult.end());
-
+
s = new Scanner("\u2028");
result = s.nextLine();
assertEquals("", result);
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(1, matchResult.end());
-
+
s = new Scanner("\u2029");
result = s.nextLine();
assertEquals("", result);
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(1, matchResult.end());
-
+
s = new Scanner("");
try {
result = s.nextLine();
- fail("Should throw NoSuchElementException");
- } catch (NoSuchElementException e) {
- // expected
+ fail();
+ } catch (NoSuchElementException expected) {
}
try {
s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
s = new Scanner("Ttest");
@@ -5570,14 +5437,14 @@
matchResult = s.match();
assertEquals(1, matchResult.start());
assertEquals(2, matchResult.end());
-
+
s = new Scanner("123 test\n ");
int value = s.nextInt();
assertEquals(123, value);
-
+
result = s.nextLine();
assertEquals(" test", result);
-
+
s = new Scanner("test\n ");
result = s.nextLine();
assertEquals("test", result);
@@ -5597,9 +5464,9 @@
// We expect read() to be called only once, otherwise we see the problem
// when reading from System.in described in Harmony-4774
assertEquals(1, cr.counter);
- assertEquals("hello", result);
+ assertEquals("hello", result);
}
-
+
/**
* @tests java.util.Scanner#hasNextLine()
*/
@@ -5608,11 +5475,10 @@
s.close();
try {
s.hasNextLine();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ fail();
+ } catch (IllegalStateException expected) {
}
-
+
s = new Scanner("test\r\ntest");
boolean result = s.hasNextLine();
assertTrue(result);
@@ -5626,21 +5492,21 @@
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(1, matchResult.end());
-
+
s = new Scanner("\u2028");
result = s.hasNextLine();
assertTrue(result);
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(1, matchResult.end());
-
+
s = new Scanner("\u2029");
result = s.hasNextLine();
assertTrue(result);
matchResult = s.match();
assertEquals(0, matchResult.start());
assertEquals(1, matchResult.end());
-
+
s = new Scanner("test\n");
assertTrue(s.hasNextLine());
matchResult = s.match();
@@ -5681,18 +5547,19 @@
Thread thread = new Thread(new Runnable() {
public void run() {
while (scanner.hasNextLine()) {
- result.add(scanner.nextLine());
+ String line = scanner.nextLine();
+ result.add(line);
}
}
});
thread.start();
for (int index = 0; index < 5; index++) {
- pos.write(("line" + index + "\n").getBytes());
+ String line = "line" + index + "\n";
+ pos.write(line.getBytes());
pos.flush();
try {
Thread.sleep(1000);
- } catch (InterruptedException e) {
- // Ignored
+ } catch (InterruptedException ignored) {
}
assertEquals(index + 1, result.size());
}
@@ -5700,8 +5567,7 @@
pos.close();
try {
thread.join(1000);
- } catch (InterruptedException e) {
- // Ignored
+ } catch (InterruptedException ignored) {
}
assertFalse(scanner.hasNextLine());
}
@@ -5724,18 +5590,45 @@
try {
serverSocket.close();
- } catch (Exception e) {
-
+ } catch (Exception ignored) {
}
try {
client.close();
- } catch (Exception e) {
- // do nothing
+ } catch (Exception ignored) {
}
try {
server.close();
- } catch (Exception e) {
- // do nothing
+ } catch (Exception ignored) {
+ }
+ }
+
+ // http://code.google.com/p/android/issues/detail?id=57050
+ public void testPerformance() throws Exception {
+ int count = 100000;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ BufferedWriter out = new BufferedWriter(new OutputStreamWriter(baos));
+ for (int i = 0; i < count; ++i) {
+ out.write(Integer.toString(123) + " ");
+ }
+ out.close();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ bais.mark(-1);
+
+ Scanner s = new Scanner(new BufferedReader(new InputStreamReader(bais)));
+ for (int i = 0; i < count; ++i) {
+ if (s.nextInt() != 123) {
+ fail();
+ }
+ }
+
+ bais.reset();
+ s = new Scanner(new BufferedReader(new InputStreamReader(bais)));
+ for (int i = 0; i < count; ++i) {
+ if (s.nextFloat() != 123.0) {
+ fail();
+ }
}
}
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
index 6f59190..a85576c 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
@@ -4,9 +4,9 @@
* The ASF licenses this file to You 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.
@@ -33,7 +33,7 @@
// charset for ascii
private static final Charset cs = Charset.forName("ascii");
private static final CharsetEncoder encoder = cs.newEncoder();
- private static final int MAXCODEPOINT = 0x7F;
+ private static final int MAXCODEPOINT = 0x7F;
/*
* @see CharsetEncoderTest#setUp()
*/
@@ -96,21 +96,21 @@
public void testEncodeMapping() throws CharacterCodingException {
encoder.reset();
-
+
for (int i =0; i <= MAXCODEPOINT; i++) {
char[] chars = Character.toChars(i);
CharBuffer cb = CharBuffer.wrap(chars);
ByteBuffer bb = encoder.encode(cb);
assertEquals(i, bb.get(0));
}
-
+
CharBuffer cb = CharBuffer.wrap("\u0080");
try {
encoder.encode(cb);
} catch (UnmappableCharacterException e) {
//expected
}
-
+
cb = CharBuffer.wrap("\ud800");
try {
encoder.encode(cb);
@@ -128,11 +128,11 @@
//expected
}
}
-
+
public void testInternalState() {
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
-
+
//normal encoding process
encoder.reset();
encoder.encode(in, out, false);
@@ -140,13 +140,13 @@
encoder.encode(in, out, true);
encoder.flush(out);
}
-
+
//reset could be called at any time
public void testInternalState_Reset() {
CharsetEncoder newEncoder = cs.newEncoder();
//Init - > reset
newEncoder.reset();
-
+
//reset - > reset
newEncoder.reset();
@@ -174,7 +174,7 @@
newEncoder.reset();
}
}
-
+
public void testInternalState_Encoding() {
CharsetEncoder newEncoder = cs.newEncoder();
//Init - > encoding
@@ -183,27 +183,27 @@
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, false);
}
-
+
//reset - > encoding
{
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
- newEncoder.reset();
+ newEncoder.reset();
newEncoder.encode(in, out, false);
}
//reset - > encoding - > encoding
{
- newEncoder.reset();
+ newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, false);
in = CharBuffer.wrap("BC");
newEncoder.encode(in, out, false);
}
-
+
//encoding_end - > encoding
{
- newEncoder.reset();
+ newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
@@ -217,7 +217,7 @@
}
//flushed - > encoding
{
- newEncoder.reset();
+ newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
@@ -231,7 +231,7 @@
}
}
}
-
+
public void testInternalState_Encoding_END() {
CharsetEncoder newEncoder = cs.newEncoder();
@@ -241,7 +241,7 @@
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
}
-
+
//Reset -> encoding_end
{
CharBuffer in = CharBuffer.wrap("A");
@@ -259,7 +259,7 @@
in = CharBuffer.wrap("BC");
newEncoder.encode(in, out, true);
}
-
+
//Reset -> encoding_end
{
newEncoder.reset();
@@ -269,7 +269,7 @@
in = CharBuffer.wrap("BC");
newEncoder.encode(in, out, true);
}
-
+
//Flushed -> encoding_end
{
newEncoder.reset();
@@ -286,10 +286,10 @@
}
}
}
-
+
public void testInternalState_Flushed() {
CharsetEncoder newEncoder = cs.newEncoder();
-
+
// init -> flushed
{
ByteBuffer out = ByteBuffer.allocate(0x10);
@@ -316,7 +316,7 @@
//expected
}
}
-
+
//encoding - > flushed
{
newEncoder.reset();
@@ -331,7 +331,7 @@
// expected
}
}
-
+
//encoding_end -> flushed
{
newEncoder.reset();
@@ -340,7 +340,7 @@
newEncoder.encode(in, out, true);
newEncoder.flush(out);
}
-
+
//flushd - > flushed
{
newEncoder.reset();
@@ -348,15 +348,10 @@
ByteBuffer out = ByteBuffer.allocate(0x10);
newEncoder.encode(in, out, true);
newEncoder.flush(out);
- try {
- newEncoder.flush(out);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
+ newEncoder.flush(out);
}
}
-
+
public void testInternalState_Encode() throws CharacterCodingException {
CharsetEncoder newEncoder = cs.newEncoder();
//Init - > encode
@@ -364,14 +359,14 @@
CharBuffer in = CharBuffer.wrap("A");
newEncoder.encode(in);
}
-
+
//Reset - > encode
{
newEncoder.reset();
CharBuffer in = CharBuffer.wrap("A");
newEncoder.encode(in);
}
-
+
//Encoding -> encode
{
newEncoder.reset();
@@ -381,7 +376,7 @@
in = CharBuffer.wrap("BC");
newEncoder.encode(in);
}
-
+
//Encoding_end -> encode
{
newEncoder.reset();
@@ -391,7 +386,7 @@
in = CharBuffer.wrap("BC");
newEncoder.encode(in);
}
-
+
//Flushed -> reset
{
newEncoder.reset();
@@ -403,17 +398,17 @@
out = newEncoder.encode(in);
}
}
-
+
public void testInternalState_from_Encode() throws CharacterCodingException {
CharsetEncoder newEncoder = cs.newEncoder();
-
+
//Encode -> Reset
{
CharBuffer in = CharBuffer.wrap("A");
newEncoder.encode(in);
newEncoder.reset();
}
-
+
// Encode -> encoding
{
CharBuffer in = CharBuffer.wrap("A");
@@ -426,12 +421,13 @@
// expected
}
}
-
+
//Encode -> Encoding_end
{
CharBuffer in = CharBuffer.wrap("A");
- newEncoder.encode(in);
ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.reset();
+ newEncoder.encode(in, out, false);
newEncoder.encode(in, out, true);
}
@@ -441,7 +437,7 @@
ByteBuffer out = newEncoder.encode(in);
newEncoder.flush(out);
}
-
+
//Encode - > encode
{
CharBuffer in = CharBuffer.wrap("A");
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
index 4ed4ab9..1a7b984 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
@@ -4,9 +4,9 @@
* The ASF licenses this file to You 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.
@@ -62,7 +62,7 @@
return null;
}
}
-
+
/**
* @tests java.nio.charset.CharsetDecoder#decode(java.nio.ByteBuffer)
*/
@@ -86,7 +86,7 @@
//
// charbuf = Charset.forName("UTF-16LE").decode(buf);
// assertEquals("Assert 2: charset UTF16LE", 0, charbuf.length());
-
+
// Regression for HARMONY-99
CharsetDecoder decoder2 = Charset.forName("UTF-16").newDecoder();
decoder2.onMalformedInput(CodingErrorAction.REPORT);
@@ -97,9 +97,9 @@
fail("Assert 3: MalformedInputException should have thrown");
} catch (MalformedInputException e) {
//expected
- }
+ }
}
-
+
/*
* Test malfunction decode(ByteBuffer)
*/
@@ -124,7 +124,7 @@
// expected
}
}
-
+
/*
* Mock charset class with malfunction decode & encode.
*/
@@ -173,8 +173,8 @@
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
throw new BufferOverflowException();
}
- }
-
+ }
+
/*
* Test the method decode(ByteBuffer) .
*/
@@ -249,16 +249,16 @@
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
/*
* When bytebuffer has a backing array...
*/
for (byte[] bytes : invalidSequences) {
try {
- decoder.decode(ByteBuffer.wrap(bytes));
- fail("No exception thrown on " + Arrays.toString(bytes));
- } catch (MalformedInputException e) {
- // expected
+ CharBuffer cb = decoder.decode(ByteBuffer.wrap(bytes));
+ fail("No exception thrown on " + Arrays.toString(bytes) + " '" + cb + "'");
+ } catch (MalformedInputException expected) {
}
}
@@ -269,10 +269,9 @@
try {
ByteBuffer bb = ByteBuffer.allocateDirect(8);
bb.put(bytes).flip();
- decoder.decode(bb);
- fail("No exception thrown on " + Arrays.toString(bytes));
- } catch (MalformedInputException e) {
- // expected
+ CharBuffer cb = decoder.decode(bb);
+ fail("No exception thrown on " + Arrays.toString(bytes) + " '" + cb + "'");
+ } catch (MalformedInputException expected) {
}
}
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
index dd514da..c3f1a8d 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
@@ -157,26 +157,36 @@
public void test_EncodeLjava_nio_CharBufferLjava_nio_ByteBufferB() throws Exception {
Charset utf8 = Charset.forName("utf-8");
CharsetEncoder encoder = utf8.newEncoder();
- CharBuffer in1 = CharBuffer.wrap("\ud800");
- CharBuffer in2 = CharBuffer.wrap("\udc00");
- ByteBuffer out = ByteBuffer.allocate(4);
+ CharBuffer char1 = CharBuffer.wrap("\ud800");
+ CharBuffer char2 = CharBuffer.wrap("\udc00");
+ ByteBuffer bytes = ByteBuffer.allocate(4);
encoder.reset();
// If we supply just the high surrogate...
- CoderResult result = encoder.encode(in1, out, false);
+ CoderResult result = encoder.encode(char1, bytes, false);
// ...we're not done...
assertTrue(result.isUnderflow());
- assertEquals(4, out.remaining());
+ assertEquals(4, bytes.remaining());
// ...but if we then supply the low surrogate...
- result = encoder.encode(in2, out, true);
+ result = encoder.encode(char2, bytes, true);
+ assertTrue(result.isUnderflow());
// ...we're done. Note that the RI loses its state in
// between the two characters, so it can't do this.
- assertEquals(0, out.remaining());
+ assertEquals(0, bytes.remaining());
+
+ // Did we get the UTF-8 for U+10000?
+ assertEquals(4, bytes.limit());
+ assertEquals((byte) 0xf0, bytes.get(0));
+ assertEquals((byte) 0x90, bytes.get(1));
+ assertEquals((byte) 0x80, bytes.get(2));
+ assertEquals((byte) 0x80, bytes.get(3));
// See what we got in the output buffer by decoding and checking that we
// get back the same surrogate pair.
- out.flip();
- CharBuffer chars = utf8.newDecoder().decode(out);
+ bytes.flip();
+ CharBuffer chars = utf8.newDecoder().decode(bytes);
+ assertEquals(0, bytes.remaining());
+ assertEquals(2, chars.limit());
assertEquals(0xd800, chars.get(0));
assertEquals(0xdc00, chars.get(1));
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
deleted file mode 100644
index 134bea6..0000000
--- a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.nio_char.tests.java.nio.charset;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.IllegalCharsetNameException;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Properties;
-import java.util.Set;
-
-import junit.framework.TestCase;
-
-public class CharsetTest extends TestCase {
-
- // Will contain names of charsets registered with IANA
- Set knownRegisteredCharsets = new HashSet();
-
- // Will contain names of charsets not known to be registered with IANA
- Set unknownRegisteredCharsets = new HashSet();
-
- /**
- * JUnit set-up method
- */
- public void setUp() {
- // Populate the known charset vars
- Set names = Charset.availableCharsets().keySet();
- for (Iterator nameItr = names.iterator(); nameItr.hasNext();) {
- String name = (String) nameItr.next();
- if (name.toLowerCase(Locale.ROOT).startsWith("x-"))
- unknownRegisteredCharsets.add(name);
- else
- knownRegisteredCharsets.add(name);
- }
- }
-
- /**
- * @tests java.nio.charset.Charset#isRegistered()
- */
- public void test_isRegistered() {
- // Regression for HARMONY-45
- for (Iterator nameItr = knownRegisteredCharsets.iterator(); nameItr.hasNext();) {
- String name = (String) nameItr.next();
- assertTrue("Assert 0: isRegistered() failed for " + name,
- Charset.forName(name).isRegistered());
- }
- for (Iterator nameItr = unknownRegisteredCharsets.iterator(); nameItr.hasNext();) {
- String name = (String) nameItr.next();
- assertFalse("Assert 0: isRegistered() failed for " + name,
- Charset.forName(name).isRegistered());
- }
- }
-
- /**
- * @tests java.nio.charset.Charset#isSupported(String)
- */
- public void testIsSupported_EmptyString() {
- // Regression for HARMONY-113
- try {
- Charset.isSupported("");
- fail("Assert 0: Should throw IllegalCharsetNameException");
- } catch (IllegalCharsetNameException e) {
- // Expected
- }
- }
-
- public void test_defaultCharset() {
- assertEquals("UTF-8", Charset.defaultCharset().name());
- }
-
- public void test_forNameLjava_lang_String() {
- /*
- * invoke forName two times with the same canonical name, it
- * should return the same reference.
- */
- Charset cs1 = Charset.forName("UTF-8");
- Charset cs2 = Charset.forName("UTF-8");
- assertSame(cs1, cs2);
-
- /*
- * test forName: invoke forName two times for the same Charset using
- * canonical name and alias, it should return the same reference.
- */
- Charset cs3 = Charset.forName("ASCII");
- Charset cs4 = Charset.forName("US-ASCII");
- assertSame(cs3, cs4);
- }
-
- /*
- * test cached decoder
- */
-// public void test_DecodeLjava_nio_ByteBuffer() throws Exception{
-// MockCharsetForDecoder cs1 = new MockCharsetForDecoder("CachedCharset",null);
-// MockCharsetForDecoder cs2 = new MockCharsetForDecoder("CachedCharset",null);
-// ByteBuffer in = ByteBuffer.wrap(new byte[]{0x00});
-// cs1.decode(in);
-// in.flip();
-// cs2.decode(in);
-// in.flip();
-// }
- /*
- * Mock Charset for cached decoder test
- */
- static class MockCharsetForDecoder extends Charset{
-
- public MockCharsetForDecoder(String canonicalName, String[] aliases){
- super(canonicalName, aliases);
- }
-
- public boolean contains(Charset charset) {
- return false;
- }
-
- public CharsetEncoder newEncoder() {
- return null;
- }
-
- public CharsetDecoder newDecoder() {
- return new MockCachedDecoder(this);
- }
-
-
- }
- /*
- * Mock decoder. Only one caller is permitted.
- */
- static class MockCachedDecoder extends CharsetDecoder {
- static MockCachedDecoder caller = null;
-
- public MockCachedDecoder(Charset cs) {
- super(cs, 1, 10);
- }
-
- /*
- * Only one caller is permitted.
- * If there's another caller, throw RuntimeException.
- */
- protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
- if(null == caller){
- caller = this;
- }else{
- if(caller != this){
- // Another instance
- fail("should use the same instance");
- }
- }
- return CoderResult.UNDERFLOW;
- }
- }
-
- /*
- * test cached encoder
- */
-// public void test_EncodeLjava_nio_CharBuffer() throws Exception {
-// MockCharsetForEncoder cs1 = new MockCharsetForEncoder("CachedCharset", null);
-// MockCharsetForEncoder cs2 = new MockCharsetForEncoder("CachedCharset", null);
-// CharBuffer in = CharBuffer.wrap("A");
-// cs1.encode(in);
-// in.flip();
-// cs2.encode(in);
-// }
-
- /*
- * Mock Charset for cached encoder test
- */
- static class MockCharsetForEncoder extends Charset {
-
- public MockCharsetForEncoder(String canonicalName, String[] aliases) {
- super(canonicalName, aliases);
- }
-
- public boolean contains(Charset charset) {
- return false;
- }
-
- public CharsetDecoder newDecoder() {
- return new MockDecoderForEncoder(this);
- }
-
- public CharsetEncoder newEncoder() {
- return new MockCachedEncoder(this);
- }
- }
-
- /*
- * Mock encoder. Only one caller is permitted.
- */
- static class MockCachedEncoder extends CharsetEncoder {
- static MockCachedEncoder caller = null;
-
- public MockCachedEncoder(Charset cs) {
- super(cs, 1, 10);
- }
-
- /*
- * Only one caller is permitted.
- */
- protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
- if (null == caller) {
- caller = this;
- } else {
- if (caller != this) {
- // Another instance
- fail("should use the same instance");
- }
- }
- return CoderResult.UNDERFLOW;
- }
- }
-
- /*
- * Mock decoder for MockCachedEncoder.
- */
- static class MockDecoderForEncoder extends CharsetDecoder {
- public MockDecoderForEncoder(Charset cs) {
- super(cs, 1, 10);
- }
-
- protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
- in.position(in.limit());
- return CoderResult.UNDERFLOW;
- }
- }
-
-}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
index 9cd59ea..7fbe9e7 100644
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
@@ -4,9 +4,9 @@
* The ASF licenses this file to You 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.
@@ -600,6 +600,15 @@
public void testFlushIllegalState() throws CharacterCodingException {
ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
CharBuffer out = CharBuffer.allocate(5);
+
+ // Illegal state: after reset.
+ decoder.reset();
+ try {
+ decoder.flush(out);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+
// Normal case: after decode with endOfInput is true
decoder.reset();
decoder.decode(in, out, true);
@@ -607,23 +616,19 @@
CoderResult result = decoder.flush(out);
assertSame(result, CoderResult.UNDERFLOW);
- // Illegal state: flush twice
- try {
- decoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- }
+ // Good state: flush twice
+ decoder.flush(out);
// Illegal state: flush after decode with endOfInput is false
decoder.reset();
decoder.decode(in, out, false);
try {
decoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
+ fail();
+ } catch (IllegalStateException expected) {
}
}
-
+
// test illegal states for decode facade
public void testDecodeFacadeIllegalState() throws CharacterCodingException {
// decode facade can be execute in anywhere
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
index ef219be..b63f4d9 100644
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
@@ -278,34 +278,36 @@
assertSame(encoder, encoder.reset());
}
- public void testFlushIllegalState() throws CharacterCodingException {
- CharBuffer in = CharBuffer.wrap("aaa");
- ByteBuffer out = ByteBuffer.allocate(5);
+ public void testFlushIllegalState() throws CharacterCodingException {
+ CharBuffer in = CharBuffer.wrap("aaa");
+ ByteBuffer out = ByteBuffer.allocate(5);
- // Normal case: after encode with endOfInput is true
- assertSame(encoder, encoder.reset());
- encoder.encode(in, out, true);
- out.rewind();
- CoderResult result = encoder.flush(out);
+ // Illegal state: after reset.
+ encoder.reset();
+ try {
+ encoder.flush(out);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
- // Illegal state: flush twice
- try {
- encoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
- }
+ // Normal case: after encode with endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(in, out, true);
+ out.rewind();
+ CoderResult result = encoder.flush(out);
- // Illegal state: flush after encode with endOfInput is false
- assertSame(encoder, encoder.reset());
- encoder.encode(in, out, false);
- try {
- encoder.flush(out);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // Expected
- }
- }
+ // Good state: flush twice
+ encoder.flush(out);
+
+ // Illegal state: flush after encode with endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(in, out, false);
+ try {
+ encoder.flush(out);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ }
public void testFlushAfterConstructing() {
ByteBuffer out = ByteBuffer.allocate(5);
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
deleted file mode 100644
index b38728a..0000000
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 tests.api.java.nio.charset;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.Charset;
-import java.nio.charset.UnsupportedCharsetException;
-import java.nio.charset.spi.CharsetProvider;
-import java.util.Iterator;
-import java.util.Vector;
-
-import junit.framework.TestCase;
-import tests.api.java.nio.charset.CharsetTest.MockCharset;
-
-/**
- * Test charset providers managed by Charset.
- */
-public class CharsetProviderTest extends TestCase {
-
- static String CONFIG_FILE1 = null;
-
-
- static MockCharset charset1 = new MockCharset("mockCharset00",
- new String[] { "mockCharset01", "mockCharset02" });
-
- static MockCharset charset2 = new MockCharset("mockCharset10",
- new String[] { "mockCharset11", "mockCharset12" });
-
- /**
- * @param arg0
- */
- public CharsetProviderTest(String arg0) {
- super(arg0);
- CONFIG_FILE1 = System.getProperty("user.dir") + "/resources";
-
- String sep = System.getProperty("file.separator");
-
- if (!CONFIG_FILE1.endsWith(sep)) {
- CONFIG_FILE1 += sep;
- }
- CONFIG_FILE1 += "META-INF" + sep + "services" + sep
- + "java.nio.charset.spi.CharsetProvider";
- }
-
- /*
- * Write the string to the config file.
- */
- private void setupFile(String path, String content) throws Exception {
- String sep = System.getProperty("file.separator");
- int sepIndex = path.lastIndexOf(sep);
- File f = new File(path.substring(0, sepIndex));
- f.mkdirs();
-
- FileOutputStream fos = new FileOutputStream(path);
- OutputStreamWriter writer = new OutputStreamWriter(fos, "UTF-8");
- try {
- writer.write(content);
- } finally {
- writer.close();
- }
- }
-
- /*
- * Write the string to the config file.
- */
- private void cleanupFile(String path) throws Exception {
- File f = new File(path);
- f.delete();
- }
-
- /*
- * Test the method isSupported(String) with charset supported by some
- * providers (multiple).
- */
- public void testIsSupported_And_ForName_NormalProvider() throws Exception {
- try {
- assertFalse(Charset.isSupported("mockCharset10"));
- assertFalse(Charset.isSupported("mockCharset11"));
- assertFalse(Charset.isSupported("mockCharset12"));
- try {
- Charset.forName("mockCharset10");
- fail("Should throw UnsupportedCharsetException!");
- } catch (UnsupportedCharsetException e) {
- // expected
- }
- try {
- Charset.forName("mockCharset11");
- fail("Should throw UnsupportedCharsetException!");
- } catch (UnsupportedCharsetException e) {
- // expected
- }
- try {
- Charset.forName("mockCharset12");
- fail("Should throw UnsupportedCharsetException!");
- } catch (UnsupportedCharsetException e) {
- // expected
- }
-
- StringBuffer sb = new StringBuffer();
- sb.append("#comment\r");
- sb.append("\n");
- sb.append("\r\n");
- sb
- .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
- sb
- .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
- setupFile(CONFIG_FILE1, sb.toString());
-
- sb = new StringBuffer();
- sb.append(" #comment\r");
- sb.append("\n");
- sb.append("\r\n");
- sb
- .append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- assertTrue(Charset.isSupported("mockCharset10"));
- // ignore case problem in mock, intended
- assertTrue(Charset.isSupported("MockCharset11"));
- assertTrue(Charset.isSupported("MockCharset12"));
- assertTrue(Charset.isSupported("MOCKCharset10"));
- // intended case problem in mock
- assertTrue(Charset.isSupported("MOCKCharset11"));
- assertTrue(Charset.isSupported("MOCKCharset12"));
-
- assertTrue(Charset.forName("mockCharset10") instanceof MockCharset);
- assertTrue(Charset.forName("mockCharset11") instanceof MockCharset);
- assertTrue(Charset.forName("mockCharset12") instanceof MockCharset);
-
- assertTrue(Charset.forName("mockCharset10") == charset2);
- // intended case problem in mock
- Charset.forName("mockCharset11");
- assertTrue(Charset.forName("mockCharset12") == charset2);
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method isSupported(String) when the configuration file contains
- * a non-existing class name.
- */
- public void testIsSupported_NonExistingClass() throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("impossible\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- Charset.isSupported("impossible");
- fail("Should throw Error!");
- } catch (Error e) {
- // expected
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method isSupported(String) when the configuration file contains
- * a non-CharsetProvider class name.
- */
- public void testIsSupported_NotCharsetProviderClass() throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("java.lang.String\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- Charset.isSupported("impossible");
- fail("Should throw ClassCastException!");
- } catch (ClassCastException e) {
- // expected
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method forName(String) when the charset provider supports a
- * built-in charset.
- */
- public void testForName_DuplicateWithBuiltInCharset() throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb
- .append("tests.api.java.nio.charset.CharsetProviderTest$MockCharsetProviderACSII\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- assertFalse(Charset.forName("us-ascii") instanceof MockCharset);
- assertFalse(Charset.availableCharsets().get("us-ascii") instanceof MockCharset);
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method forName(String) when the configuration file contains a
- * non-existing class name.
- */
- public void testForName_NonExistingClass() throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("impossible\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- Charset.forName("impossible");
- fail("Should throw Error!");
- } catch (Error e) {
- // expected
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method forName(String) when the configuration file contains a
- * non-CharsetProvider class name.
- */
- public void testForName_NotCharsetProviderClass() throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("java.lang.String\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- Charset.forName("impossible");
- fail("Should throw ClassCastException!");
- } catch (ClassCastException e) {
- // expected
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method availableCharsets() with charset supported by some
- * providers (multiple).
- */
- public void testAvailableCharsets_NormalProvider() throws Exception {
- try {
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset10"));
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset11"));
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset12"));
-
- StringBuffer sb = new StringBuffer();
- sb.append("#comment\r");
- sb.append("\n");
- sb.append("\r\n");
- sb
- .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
- sb
- .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
- setupFile(CONFIG_FILE1, sb.toString());
-
- sb = new StringBuffer();
- sb.append("#comment\r");
- sb.append("\n");
- sb.append("\r\n");
- sb
- .append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- assertTrue(Charset.availableCharsets().containsKey("mockCharset00"));
- assertTrue(Charset.availableCharsets().containsKey("MOCKCharset00"));
- assertTrue(Charset.availableCharsets().get("mockCharset00") instanceof MockCharset);
- assertTrue(Charset.availableCharsets().get("MOCKCharset00") instanceof MockCharset);
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset01"));
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset02"));
-
- assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
- assertTrue(Charset.availableCharsets().get("MOCKCharset10") == charset2);
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset11"));
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset12"));
-
- assertTrue(Charset.availableCharsets().containsKey("mockCharset10"));
- assertTrue(Charset.availableCharsets().containsKey("MOCKCharset10"));
- assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset11"));
- assertFalse(Charset.availableCharsets()
- .containsKey("mockCharset12"));
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method availableCharsets(String) when the configuration file
- * contains a non-existing class name.
- */
- public void testAvailableCharsets_NonExistingClass() throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("impossible\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- Charset.availableCharsets();
- fail("Should throw Error!");
- } catch (Error e) {
- // expected
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method availableCharsets(String) when the configuration file
- * contains a non-CharsetProvider class name.
- */
- public void testAvailableCharsets_NotCharsetProviderClass()
- throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("java.lang.String\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- Charset.availableCharsets();
- fail("Should throw ClassCastException!");
- } catch (ClassCastException e) {
- // expected
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Test the method availableCharsets(String) when the configuration file
- * contains an illegal string.
- */
- public void testAvailableCharsets_IllegalString() throws Exception {
- try {
- StringBuffer sb = new StringBuffer();
- sb.append("java String\r");
- setupFile(CONFIG_FILE1, sb.toString());
-
- Charset.availableCharsets();
- fail("Should throw Error!");
- } catch (Error e) {
- // expected
- } finally {
- cleanupFile(CONFIG_FILE1);
- }
- }
-
- /*
- * Mock charset provider.
- */
- public static class MockCharsetProvider extends CharsetProvider {
-
- public Charset charsetForName(String charsetName) {
- if ("MockCharset10".equalsIgnoreCase(charsetName)
- || "MockCharset11".equalsIgnoreCase(charsetName)
- || "MockCharset12".equalsIgnoreCase(charsetName)) {
- return charset2;
- }
- return null;
- }
-
- public Iterator charsets() {
- Vector v = new Vector();
- v.add(charset2);
- return v.iterator();
- }
- }
-
- /*
- * Another mock charset provider providing build-in charset "ascii".
- */
- public static class MockCharsetProviderACSII extends CharsetProvider {
-
- public Charset charsetForName(String charsetName) {
- if ("US-ASCII".equalsIgnoreCase(charsetName)
- || "ASCII".equalsIgnoreCase(charsetName)) {
- return new MockCharset("US-ASCII", new String[] { "ASCII" });
- }
- return null;
- }
-
- public Iterator charsets() {
- Vector v = new Vector();
- v.add(new MockCharset("US-ASCII", new String[] { "ASCII" }));
- return v.iterator();
- }
- }
-
-}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
index c658c48..92f230e 100644
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
@@ -23,11 +23,15 @@
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
import java.nio.charset.spi.CharsetProvider;
+import java.nio.charset.UnsupportedCharsetException;
import java.security.Permission;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
+import java.util.Set;
import java.util.SortedMap;
import java.util.Vector;
@@ -38,802 +42,865 @@
*/
public class CharsetTest extends TestCase {
- static MockCharset charset1 = new MockCharset("mockCharset00",
- new String[] { "mockCharset01", "mockCharset02" });
+ public void test_allAvailableCharsets() throws Exception {
+ // Check that we can instantiate every Charset, CharsetDecoder, and CharsetEncoder.
+ for (String charsetName : Charset.availableCharsets().keySet()) {
+ if (charsetName.equals("UTF-32")) {
+ // Our UTF-32 is broken. http://b/2702411
+ // TODO: remove this hack when UTF-32 is fixed.
+ continue;
+ }
- static MockCharset charset2 = new MockCharset("mockCharset10",
- new String[] { "mockCharset11", "mockCharset12" });
+ Charset cs = Charset.forName(charsetName);
+ assertNotNull(cs.newDecoder());
+ if (cs.canEncode()) {
+ CharsetEncoder enc = cs.newEncoder();
+ assertNotNull(enc);
+ assertNotNull(enc.replacement());
+ }
+ }
+ }
- /*
- * @see TestCase#setUp()
- */
- protected void setUp() throws Exception {
- super.setUp();
- }
+ public void test_defaultCharset() {
+ assertEquals("UTF-8", Charset.defaultCharset().name());
+ }
- /*
- * @see TestCase#tearDown()
- */
- protected void tearDown() throws Exception {
- super.tearDown();
- }
+ public void test_isRegistered() {
+ // Regression for HARMONY-45
- /*
- * Test the required 6 charsets are supported.
- */
- public void testRequiredCharsetSupported() {
- assertTrue(Charset.isSupported("US-ASCII"));
- assertTrue(Charset.isSupported("ASCII"));
- assertTrue(Charset.isSupported("ISO-8859-1"));
- assertTrue(Charset.isSupported("ISO8859_1"));
- assertTrue(Charset.isSupported("UTF-8"));
- assertTrue(Charset.isSupported("UTF8"));
- assertTrue(Charset.isSupported("UTF-16"));
- assertTrue(Charset.isSupported("UTF-16BE"));
- assertTrue(Charset.isSupported("UTF-16LE"));
+ // Will contain names of charsets registered with IANA
+ Set<String> knownRegisteredCharsets = new HashSet<String>();
- Charset c1 = Charset.forName("US-ASCII");
- assertEquals("US-ASCII", Charset.forName("US-ASCII").name());
- assertEquals("US-ASCII", Charset.forName("ASCII").name());
- assertEquals("ISO-8859-1", Charset.forName("ISO-8859-1").name());
- assertEquals("ISO-8859-1", Charset.forName("ISO8859_1").name());
- assertEquals("UTF-8", Charset.forName("UTF-8").name());
- assertEquals("UTF-8", Charset.forName("UTF8").name());
- assertEquals("UTF-16", Charset.forName("UTF-16").name());
- assertEquals("UTF-16BE", Charset.forName("UTF-16BE").name());
- assertEquals("UTF-16LE", Charset.forName("UTF-16LE").name());
+ // Will contain names of charsets not known to be registered with IANA
+ Set<String> unknownRegisteredCharsets = new HashSet<String>();
- assertNotSame(Charset.availableCharsets(), Charset.availableCharsets());
- // assertSame(Charset.forName("US-ASCII"), Charset.availableCharsets()
- // .get("US-ASCII"));
- // assertSame(Charset.forName("US-ASCII"), c1);
- assertTrue(Charset.availableCharsets().containsKey("US-ASCII"));
- assertTrue(Charset.availableCharsets().containsKey("ISO-8859-1"));
- assertTrue(Charset.availableCharsets().containsKey("UTF-8"));
- assertTrue(Charset.availableCharsets().containsKey("UTF-16"));
- assertTrue(Charset.availableCharsets().containsKey("UTF-16BE"));
- assertTrue(Charset.availableCharsets().containsKey("UTF-16LE"));
- }
-
- /*
- * Test the method isSupported(String) with null.
- */
- public void testIsSupported_Null() {
- try {
- Charset.isSupported(null);
- fail("Should throw IllegalArgumentException!");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- /*
- * Test the method isSupported(String) with empty string.
- *
- */
- public void testIsSupported_EmptyString() {
- try {
- Charset.isSupported("");
- } catch (IllegalArgumentException e) {
- // FIXME: Commented out since RI does throw IAE
- // fail("Should not throw IllegalArgumentException!");
- }
- }
-
- /*
- * Test the method isSupported(String) with a string starting with ".".
- *
- */
- public void testIsSupported_InvalidInitialCharacter() {
- try {
- Charset.isSupported(".char");
- } catch (IllegalArgumentException e) {
- fail("Should not throw IllegalArgumentException!");
- }
- }
-
- /*
- * Test the method isSupported(String) with illegal charset name.
- */
- public void testIsSupported_IllegalName() {
- try {
- Charset.isSupported(" ///#$$");
- fail("Should throw IllegalCharsetNameException!");
- } catch (IllegalCharsetNameException e) {
- // expected
- }
- }
-
- /*
- * Test the method isSupported(String) with not supported charset name.
- */
- public void testIsSupported_NotSupported() {
- assertFalse(Charset.isSupported("impossible"));
- }
-
- /*
- * Test the method forName(String) with null.
- */
- public void testForName_Null() {
- try {
- Charset.forName(null);
- fail("Should throw IllegalArgumentException!");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- /*
- * Test the method forName(String) with empty string.
- */
- public void testForName_EmptyString() {
- try {
- Charset.forName("");
- fail("Should throw IllegalArgumentException!");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- /*
- * Test the method forName(String) with a string starting with ".".
- */
- public void testForName_InvalidInitialCharacter() {
- try {
- Charset.forName(".char");
- fail("Should throw IllegalArgumentException!");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- /*
- * Test the method forName(String) with illegal charset name.
- */
- public void testForName_IllegalName() {
- try {
- Charset.forName(" ///#$$");
- fail("Should throw IllegalCharsetNameException!");
- } catch (IllegalCharsetNameException e) {
- // expected
- }
- }
-
- /*
- * Test the method forName(String) with not supported charset name.
- */
- public void testForName_NotSupported() {
- try {
- Charset.forName("impossible");
- fail("Should throw UnsupportedCharsetException!");
- } catch (UnsupportedCharsetException e) {
- // expected
- }
- }
-
- /*
- * Test the constructor with normal parameter values.
- */
- public void testConstructor_Normal() {
- final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
- MockCharset c = new MockCharset(mockName, new String[] { "mock" });
- assertEquals(mockName, c.name());
- assertEquals(mockName, c.displayName());
- assertEquals(mockName, c.displayName(Locale.getDefault()));
- assertEquals("mock", c.aliases().toArray()[0]);
- assertEquals(1, c.aliases().toArray().length);
- }
-
- /*
- * Test the constructor with empty canonical name.
- *
- */
- public void testConstructor_EmptyCanonicalName() {
- try {
- new MockCharset("", new String[0]);
- } catch (IllegalCharsetNameException e) {
- // FIXME: Commented out since RI does throw IAE
- // fail("Should not throw IllegalArgumentException!");
- }
- }
-
- /*
- * Test the constructor with illegal canonical name: starting with neither a
- * digit nor a letter.
- *
- */
- public void testConstructor_IllegalCanonicalName_Initial() {
- try {
- new MockCharset("-123", new String[] { "mock" });
- } catch (IllegalCharsetNameException e) {
- fail("Should not throw IllegalArgumentException!");
- }
- }
-
- /*
- * Test the constructor with illegal canonical name, illegal character in
- * the middle.
- */
- public void testConstructor_IllegalCanonicalName_Middle() {
- try {
- new MockCharset("1%%23", new String[] { "mock" });
- fail("Should throw IllegalCharsetNameException!");
- } catch (IllegalCharsetNameException e) {
- // expected
- }
- try {
- new MockCharset("1//23", new String[] { "mock" });
- fail("Should throw IllegalCharsetNameException!");
- } catch (IllegalCharsetNameException e) {
- // expected
- }
- }
-
- /*
- * Test the constructor with null canonical name.
- */
- public void testConstructor_NullCanonicalName() {
- try {
- MockCharset c = new MockCharset(null, new String[] { "mock" });
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the constructor with null aliases.
- */
- public void testConstructor_NullAliases() {
- MockCharset c = new MockCharset("mockChar", null);
- assertEquals("mockChar", c.name());
- assertEquals("mockChar", c.displayName());
- assertEquals("mockChar", c.displayName(Locale.getDefault()));
- assertEquals(0, c.aliases().toArray().length);
- }
-
- /*
- * Test the constructor with a null aliases.
- */
- public void testConstructor_NullAliase() {
- try {
- new MockCharset("mockChar", new String[] { "mock", null });
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the constructor with no aliases.
- */
- public void testConstructor_NoAliases() {
- MockCharset c = new MockCharset("mockChar", new String[0]);
- assertEquals("mockChar", c.name());
- assertEquals("mockChar", c.displayName());
- assertEquals("mockChar", c.displayName(Locale.getDefault()));
- assertEquals(0, c.aliases().toArray().length);
- }
-
- /*
- * Test the constructor with empty aliases.
- *
- */
- public void testConstructor_EmptyAliases() {
- try {
- new MockCharset("mockChar", new String[] { "" });
- } catch (IllegalCharsetNameException e) {
- // FIXME: Commented out since RI does throw IAE
- // fail("Should not throw IllegalArgumentException!");
- }
- }
-
- /*
- * Test the constructor with illegal aliases: starting with neither a digit
- * nor a letter.
- *
- */
- public void testConstructor_IllegalAliases_Initial() {
- try {
- new MockCharset("mockChar", new String[] { "mock", "-123" });
- } catch (IllegalCharsetNameException e) {
- fail("Should not throw IllegalArgumentException!");
- }
- }
-
- /*
- * Test the constructor with illegal aliase, illegal character in the
- * middle.
- */
- public void testConstructor_IllegalAliases_Middle() {
- try {
- new MockCharset("mockChar", new String[] { "mock", "22##ab" });
- fail("Should throw IllegalCharsetNameException!");
- } catch (IllegalCharsetNameException e) {
- // expected
- }
- try {
- new MockCharset("mockChar", new String[] { "mock", "22%%ab" });
- fail("Should throw IllegalCharsetNameException!");
- } catch (IllegalCharsetNameException e) {
- // expected
- }
- }
-
- /*
- * Test the method aliases() with multiple aliases. Most conditions have
- * been tested in the testcases for the constructors.
- */
- public void testAliases_Multiple() {
- final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
- MockCharset c = new MockCharset("mockChar", new String[] { "mock",
- mockName, "mock2" });
- assertEquals("mockChar", c.name());
- assertEquals(3, c.aliases().size());
- assertTrue(c.aliases().contains("mock"));
- assertTrue(c.aliases().contains(mockName));
- assertTrue(c.aliases().contains("mock2"));
-
- try {
- c.aliases().clear();
- fail("Should throw UnsupportedOperationException!");
- } catch (UnsupportedOperationException e) {
- // expected
- }
- }
-
- /*
- * Test the method aliases() with duplicate aliases, one same with its
- * canonical name.
- */
- public void testAliases_Duplicate() {
- final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
- MockCharset c = new MockCharset("mockChar", new String[] { "mockChar",
- "mock", mockName, "mock", "mockChar", "mock", "mock2" });
- assertEquals("mockChar", c.name());
- assertEquals(4, c.aliases().size());
- assertTrue(c.aliases().contains("mockChar"));
- assertTrue(c.aliases().contains("mock"));
- assertTrue(c.aliases().contains(mockName));
- assertTrue(c.aliases().contains("mock2"));
- }
-
- /*
- * Test the method canEncode(). Test the default return value.
- */
- public void testCanEncode() {
- MockCharset c = new MockCharset("mock", null);
- assertTrue(c.canEncode());
- }
-
- /*
- * Test the method isRegistered(). Test the default return value.
- */
- public void testIsRegistered() {
- MockCharset c = new MockCharset("mock", null);
- assertTrue(c.isRegistered());
- }
-
- /*
- * The name() method has been tested by the testcases for the constructor.
- */
- public void testName() {
- // already covered by testConstructor_XXX series
- }
-
- /*
- * The displayName() method have been tested by the testcases for the
- * constructor.
- */
- public void testDisplayName() {
- // already covered by testConstructor_XXX series
- }
-
- /*
- * Test displayName(Locale) with null.
- */
- public void testDisplayName_Locale_Null() {
- MockCharset c = new MockCharset("mock", null);
- assertEquals("mock", c.displayName(null));
- }
-
- /*
- * Test the method compareTo(Object) with normal conditions.
- */
- public void testCompareTo_Normal() {
- MockCharset c1 = new MockCharset("mock", null);
- assertEquals(0, c1.compareTo(c1));
-
- MockCharset c2 = new MockCharset("Mock", null);
- assertEquals(0, c1.compareTo(c2));
-
- c2 = new MockCharset("mock2", null);
- assertTrue(c1.compareTo(c2) < 0);
- assertTrue(c2.compareTo(c1) > 0);
-
- c2 = new MockCharset("mack", null);
- assertTrue(c1.compareTo(c2) > 0);
- assertTrue(c2.compareTo(c1) < 0);
-
- c2 = new MockCharset("m.", null);
- assertTrue(c1.compareTo(c2) > 0);
- assertTrue(c2.compareTo(c1) < 0);
-
- c2 = new MockCharset("m:", null);
- assertEquals("mock".compareToIgnoreCase("m:"), c1.compareTo(c2));
- assertEquals("m:".compareToIgnoreCase("mock"), c2.compareTo(c1));
-
- c2 = new MockCharset("m-", null);
- assertTrue(c1.compareTo(c2) > 0);
- assertTrue(c2.compareTo(c1) < 0);
-
- c2 = new MockCharset("m_", null);
- assertTrue(c1.compareTo(c2) > 0);
- assertTrue(c2.compareTo(c1) < 0);
- }
-
- /*
- * Test the method compareTo(Object) with null param.
- */
- public void testCompareTo_Null() {
- MockCharset c1 = new MockCharset("mock", null);
- try {
- c1.compareTo(null);
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the method compareTo(Object) with another kind of charset object.
- */
- public void testCompareTo_DiffCharsetClass() {
- MockCharset c1 = new MockCharset("mock", null);
- MockCharset2 c2 = new MockCharset2("Mock", new String[] { "myname" });
- assertEquals(0, c1.compareTo(c2));
- assertEquals(0, c2.compareTo(c1));
- }
-
- /*
- * Test the method equals(Object) with null param.
- */
- public void testEquals_Normal() {
- MockCharset c1 = new MockCharset("mock", null);
- MockCharset2 c2 = new MockCharset2("mock", null);
- assertTrue(c1.equals(c2));
- assertTrue(c2.equals(c1));
-
- c2 = new MockCharset2("Mock", null);
- assertFalse(c1.equals(c2));
- assertFalse(c2.equals(c1));
- }
-
- /*
- * Test the method equals(Object) with normal conditions.
- */
- public void testEquals_Null() {
- MockCharset c1 = new MockCharset("mock", null);
- assertFalse(c1.equals(null));
- }
-
- /*
- * Test the method equals(Object) with another kind of charset object.
- */
- public void testEquals_NonCharsetObject() {
- MockCharset c1 = new MockCharset("mock", null);
- assertFalse(c1.equals("test"));
- }
-
- /*
- * Test the method equals(Object) with another kind of charset object.
- */
- public void testEquals_DiffCharsetClass() {
- MockCharset c1 = new MockCharset("mock", null);
- MockCharset2 c2 = new MockCharset2("mock", null);
- assertTrue(c1.equals(c2));
- assertTrue(c2.equals(c1));
- }
-
- /*
- * Test the method hashCode().
- */
- public void testHashCode_DiffCharsetClass() {
- MockCharset c1 = new MockCharset("mock", null);
- assertEquals(c1.hashCode(), "mock".hashCode());
-
- final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
- c1 = new MockCharset(mockName, new String[] { "mockChar", "mock",
- mockName, "mock", "mockChar", "mock", "mock2" });
- assertEquals(mockName.hashCode(), c1.hashCode());
- }
-
- /*
- * Test the method encode(CharBuffer) under normal condition.
- */
- public void testEncode_CharBuffer_Normal() throws Exception {
- MockCharset c1 = new MockCharset("testEncode_CharBuffer_Normal_mock", null);
- ByteBuffer bb = c1.encode(CharBuffer.wrap("abcdefg"));
- assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
- bb = c1.encode(CharBuffer.wrap(""));
- assertEquals("", new String(bb.array(), "iso8859-1"));
- }
-
- /*
- * Test the method encode(CharBuffer) with an unmappable char.
- */
- public void testEncode_CharBuffer_Unmappable() throws Exception {
- Charset c1 = Charset.forName("iso8859-1");
- ByteBuffer bb = c1.encode(CharBuffer.wrap("abcd\u5D14efg"));
- assertEquals(new String(bb.array(), "iso8859-1"), "abcd"
- + new String(c1.newEncoder().replacement(), "iso8859-1")
- + "efg");
- }
-
- /*
- * Test the method encode(CharBuffer) with null CharBuffer.
- */
- public void testEncode_CharBuffer_NullCharBuffer() {
- MockCharset c = new MockCharset("mock", null);
- try {
- c.encode((CharBuffer) null);
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the method encode(CharBuffer) with null encoder.
- */
- public void testEncode_CharBuffer_NullEncoder() {
- MockCharset2 c = new MockCharset2("mock2", null);
- try {
- c.encode(CharBuffer.wrap("hehe"));
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the method encode(String) under normal condition.
- */
- public void testEncode_String_Normal() throws Exception {
- MockCharset c1 = new MockCharset("testEncode_String_Normal_mock", null);
- ByteBuffer bb = c1.encode("abcdefg");
- assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
- bb = c1.encode("");
- assertEquals("", new String(bb.array(), "iso8859-1"));
- }
-
- /*
- * Test the method encode(String) with an unmappable char.
- */
- public void testEncode_String_Unmappable() throws Exception {
- Charset c1 = Charset.forName("iso8859-1");
- ByteBuffer bb = c1.encode("abcd\u5D14efg");
- assertEquals(new String(bb.array(), "iso8859-1"), "abcd"
- + new String(c1.newEncoder().replacement(), "iso8859-1")
- + "efg");
- }
-
- /*
- * Test the method encode(String) with null CharBuffer.
- */
- public void testEncode_String_NullString() {
- MockCharset c = new MockCharset("mock", null);
- try {
- c.encode((String) null);
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the method encode(String) with null encoder.
- */
- public void testEncode_String_NullEncoder() {
-
- MockCharset2 c = new MockCharset2("mock2", null);
- try {
- c.encode("hehe");
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the method decode(ByteBuffer) under normal condition.
- */
- public void testDecode_Normal() throws Exception {
- MockCharset c1 = new MockCharset("mock", null);
- CharBuffer cb = c1.decode(ByteBuffer.wrap("abcdefg"
- .getBytes("iso8859-1")));
- assertEquals("abcdefg", new String(cb.array()));
- cb = c1.decode(ByteBuffer.wrap("".getBytes("iso8859-1")));
- assertEquals("", new String(cb.array()));
- }
-
- /*
- * Test the method decode(ByteBuffer) with a malformed input.
- */
- public void testDecode_Malformed() throws Exception {
- Charset c1 = Charset.forName("iso8859-1");
- CharBuffer cb = c1.decode(ByteBuffer.wrap("abcd\u5D14efg"
- .getBytes("iso8859-1")));
- byte[] replacement = c1.newEncoder().replacement();
- assertEquals(new String(cb.array()).trim(), "abcd" + new String(replacement, "iso8859-1")
- + "efg");
- }
-
- /*
- * Test the method decode(ByteBuffer) with null CharBuffer.
- */
- public void testDecode_NullByteBuffer() {
- MockCharset c = new MockCharset("mock", null);
- try {
- c.decode(null);
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the method decode(ByteBuffer) with null encoder.
- */
- public void testDecode_NullDecoder() {
- MockCharset2 c = new MockCharset2("mock2", null);
- try {
- c.decode(ByteBuffer.wrap("hehe".getBytes()));
- fail("Should throw NullPointerException!");
- } catch (NullPointerException e) {
- // expected
- }
- }
-
- /*
- * Test the method toString().
- */
- public void testToString() {
- MockCharset c1 = new MockCharset("mock", null);
- assertTrue(-1 != c1.toString().indexOf("mock"));
- }
-
- /**
- * @tests java.nio.charset.Charset#availableCharsets()
- */
- public void test_availableCharsets() throws Exception {
- // regression test for Harmony-1051
- ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(null);
- SortedMap<String, Charset> charsets = Charset.availableCharsets();
- // make sure "mockCharset00" is loaded by MockCharsetProvider
- assertTrue(charsets.containsKey("mockCharset00"));
- } finally {
- Thread.currentThread().setContextClassLoader(originalClassLoader);
- }
+ Set<String> names = Charset.availableCharsets().keySet();
+ for (Iterator nameItr = names.iterator(); nameItr.hasNext();) {
+ String name = (String) nameItr.next();
+ if (name.toLowerCase(Locale.ROOT).startsWith("x-")) {
+ unknownRegisteredCharsets.add(name);
+ } else {
+ knownRegisteredCharsets.add(name);
+ }
}
- /**
- * @tests java.nio.charset.Charset#availableCharsets()
- */
- public void test_forNameLString() throws Exception {
- // regression test for Harmony-1051
- ClassLoader originalClassLoader = Thread.currentThread()
- .getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(null);
- // make sure "mockCharset00" is loaded by MockCharsetProvider
- assertNotNull(Charset.forName("mockCharset00"));
- } finally {
- Thread.currentThread().setContextClassLoader(originalClassLoader);
+ for (Iterator nameItr = knownRegisteredCharsets.iterator(); nameItr.hasNext();) {
+ String name = (String) nameItr.next();
+ Charset cs = Charset.forName(name);
+ if (!cs.isRegistered()) {
+ System.err.println("isRegistered was false for " + name + " " + cs.name() + " " + cs.aliases());
+ }
+ assertTrue("isRegistered was false for " + name + " " + cs.name() + " " + cs.aliases(), cs.isRegistered());
+ }
+ for (Iterator nameItr = unknownRegisteredCharsets.iterator(); nameItr.hasNext();) {
+ String name = (String) nameItr.next();
+ Charset cs = Charset.forName(name);
+ assertFalse("isRegistered was true for " + name + " " + cs.name() + " " + cs.aliases(), cs.isRegistered());
+ }
+ }
+
+ public void test_guaranteedCharsetsAvailable() throws Exception {
+ // All Java implementations must support these charsets.
+ assertNotNull(Charset.forName("ISO-8859-1"));
+ assertNotNull(Charset.forName("US-ASCII"));
+ assertNotNull(Charset.forName("UTF-16"));
+ assertNotNull(Charset.forName("UTF-16BE"));
+ assertNotNull(Charset.forName("UTF-16LE"));
+ assertNotNull(Charset.forName("UTF-8"));
+ }
+
+ // http://code.google.com/p/android/issues/detail?id=42769
+ public void test_42769() throws Exception {
+ ArrayList<Thread> threads = new ArrayList<Thread>();
+ for (int i = 0; i < 10; ++i) {
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ for (int i = 0; i < 50; ++i) {
+ Charset.availableCharsets();
+ }
}
+ });
+ threads.add(t);
}
- /*
- * Mock charset class.
- */
- static final class MockCharset extends Charset {
+ for (Thread t : threads) {
+ t.start();
+ }
+ for (Thread t : threads) {
+ t.join();
+ }
+ }
- public MockCharset(String canonicalName, String[] aliases) {
- super(canonicalName, aliases);
- }
+ public void test_have_canonical_EUC_JP() throws Exception {
+ assertEquals("EUC-JP", Charset.forName("EUC-JP").name());
+ }
- public boolean contains(Charset cs) {
- return false;
- }
+ public void test_EUC_JP_replacement_character() throws Exception {
+ // We have text either side of the replacement character, because all kinds of errors
+ // could lead to a replacement character being returned.
+ assertEncodes(Charset.forName("EUC-JP"), " \ufffd ", ' ', 0xf4, 0xfe, ' ');
+ assertDecodes(Charset.forName("EUC-JP"), " \ufffd ", ' ', 0xf4, 0xfe, ' ');
+ }
- public CharsetDecoder newDecoder() {
- return new MockDecoder(this);
- }
+ public void test_SCSU_replacement_character() throws Exception {
+ // We have text either side of the replacement character, because all kinds of errors
+ // could lead to a replacement character being returned.
+ assertEncodes(Charset.forName("SCSU"), " \ufffd ", ' ', 14, 0xff, 0xfd, ' ');
+ assertDecodes(Charset.forName("SCSU"), " \ufffd ", ' ', 14, 0xff, 0xfd, ' ');
+ }
- public CharsetEncoder newEncoder() {
- return new MockEncoder(this);
- }
- }
+ public void test_Shift_JIS_replacement_character() throws Exception {
+ // We have text either side of the replacement character, because all kinds of errors
+ // could lead to a replacement character being returned.
+ assertEncodes(Charset.forName("Shift_JIS"), " \ufffd ", ' ', 0xfc, 0xfc, ' ');
+ assertDecodes(Charset.forName("Shift_JIS"), " \ufffd ", ' ', 0xfc, 0xfc, ' ');
+ }
- /*
- * Another mock charset class.
- */
- static class MockCharset2 extends Charset {
+ public void test_UTF_16() throws Exception {
+ Charset cs = Charset.forName("UTF-16");
+ // Writes big-endian, with a big-endian BOM.
+ assertEncodes(cs, "a\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
+ // Reads whatever the BOM tells it to read...
+ assertDecodes(cs, "a\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
+ assertDecodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
+ // ...and defaults to reading big-endian if there's no BOM.
+ assertDecodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
+ }
- public MockCharset2(String canonicalName, String[] aliases) {
- super(canonicalName, aliases);
- }
+ public void test_UTF_16BE() throws Exception {
+ Charset cs = Charset.forName("UTF-16BE");
+ // Writes big-endian, with no BOM.
+ assertEncodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
+ // Treats a little-endian BOM as an error and continues to read big-endian.
+ // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
+ assertDecodes(cs, "\ufffda\u0666", 0xff, 0xfe, 0, 'a', 0x06, 0x66);
+ // Accepts a big-endian BOM and includes U+FEFF in the decoded output.
+ assertDecodes(cs, "\ufeffa\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
+ // Defaults to reading big-endian.
+ assertDecodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
+ }
- public boolean contains(Charset cs) {
- return false;
- }
+ public void test_UTF_16LE() throws Exception {
+ Charset cs = Charset.forName("UTF-16LE");
+ // Writes little-endian, with no BOM.
+ assertEncodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
+ // Accepts a little-endian BOM and includes U+FEFF in the decoded output.
+ assertDecodes(cs, "\ufeffa\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
+ // Treats a big-endian BOM as an error and continues to read little-endian.
+ // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
+ assertDecodes(cs, "\ufffda\u0666", 0xfe, 0xff, 'a', 0, 0x66, 0x06);
+ // Defaults to reading little-endian.
+ assertDecodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
+ }
- public CharsetDecoder newDecoder() {
- return null;
- }
+ public void test_x_UTF_16LE_BOM() throws Exception {
+ Charset cs = Charset.forName("x-UTF-16LE-BOM");
+ // Writes little-endian, with a BOM.
+ assertEncodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
+ // Accepts a little-endian BOM and swallows the BOM.
+ assertDecodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
+ // Swallows a big-endian BOM, but continues to read little-endian!
+ assertDecodes(cs, "\u6100\u6606", 0xfe, 0xff, 'a', 0, 0x66, 0x06);
+ // Defaults to reading little-endian.
+ assertDecodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
+ }
- public CharsetEncoder newEncoder() {
- return null;
- }
- }
+ public void test_UTF_32() throws Exception {
+ Charset cs = Charset.forName("UTF-32");
+ // Writes big-endian, with no BOM.
+ assertEncodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ // Reads whatever the BOM tells it to read...
+ assertDecodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ assertDecodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ // ...and defaults to reading big-endian if there's no BOM.
+ assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ }
- /*
- * Mock encoder.
- */
- static class MockEncoder extends java.nio.charset.CharsetEncoder {
+ public void test_UTF_32BE() throws Exception {
+ Charset cs = Charset.forName("UTF-32BE");
+ // Writes big-endian, with no BOM.
+ assertEncodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ // Treats a little-endian BOM as an error and continues to read big-endian.
+ // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
+ assertDecodes(cs, "\ufffda\u0666", 0xff, 0xfe, 0, 0, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ // Accepts a big-endian BOM and swallows the BOM.
+ assertDecodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ // Defaults to reading big-endian.
+ assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ }
- public MockEncoder(Charset cs) {
- super(cs, 1, 3, new byte[] { (byte) '?' });
- }
+ public void test_UTF_32LE() throws Exception {
+ Charset cs = Charset.forName("UTF-32LE");
+ // Writes little-endian, with no BOM.
+ assertEncodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ // Accepts a little-endian BOM and swallows the BOM.
+ assertDecodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ // Treats a big-endian BOM as an error and continues to read little-endian.
+ // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
+ assertDecodes(cs, "\ufffda\u0666", 0, 0, 0xfe, 0xff, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ // Defaults to reading little-endian.
+ assertDecodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ }
- protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
- while (in.remaining() > 0) {
- out.put((byte) in.get());
- // out.put((byte) '!');
- }
- return CoderResult.UNDERFLOW;
- }
- }
+ public void test_X_UTF_32BE_BOM() throws Exception {
+ Charset cs = Charset.forName("X-UTF-32BE-BOM");
+ // Writes big-endian, with a big-endian BOM.
+ assertEncodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ // Treats a little-endian BOM as an error and continues to read big-endian.
+ // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
+ assertDecodes(cs, "\ufffda\u0666", 0xff, 0xfe, 0, 0, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ // Swallows a big-endian BOM, and continues to read big-endian.
+ assertDecodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ // Defaults to reading big-endian.
+ assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
+ }
- /*
- * Mock decoder.
- */
- static class MockDecoder extends java.nio.charset.CharsetDecoder {
+ public void test_X_UTF_32LE_BOM() throws Exception {
+ Charset cs = Charset.forName("X-UTF-32LE-BOM");
+ // Writes little-endian, with a little-endian BOM.
+ assertEncodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ // Accepts a little-endian BOM and swallows the BOM.
+ assertDecodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ // Treats a big-endian BOM as an error and continues to read little-endian.
+ // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
+ assertDecodes(cs, "\ufffda\u0666", 0, 0, 0xfe, 0xff, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ // Defaults to reading little-endian.
+ assertDecodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
+ }
- public MockDecoder(Charset cs) {
- super(cs, 1, 10);
- }
+ private byte[] toByteArray(int[] ints) {
+ byte[] result = new byte[ints.length];
+ for (int i = 0; i < ints.length; ++i) {
+ result[i] = (byte) ints[i];
+ }
+ return result;
+ }
- protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
- while (in.remaining() > 0) {
- out.put((char) in.get());
- }
- return CoderResult.UNDERFLOW;
- }
- }
+ private void assertEncodes(Charset cs, String s, int... expectedByteInts) throws Exception {
+ ByteBuffer out = cs.encode(s);
+ byte[] bytes = new byte[out.remaining()];
+ out.get(bytes);
+ assertEquals(Arrays.toString(toByteArray(expectedByteInts)), Arrays.toString(bytes));
+ }
- /*
- * Mock charset provider.
- */
- public static class MockCharsetProvider extends CharsetProvider {
+ private void assertDecodes(Charset cs, String s, int... byteInts) throws Exception {
+ ByteBuffer in = ByteBuffer.wrap(toByteArray(byteInts));
+ CharBuffer out = cs.decode(in);
+ assertEquals(s, out.toString());
+ }
- public Charset charsetForName(String charsetName) {
- if ("MockCharset00".equalsIgnoreCase(charsetName)
- || "MockCharset01".equalsIgnoreCase(charsetName)
- || "MockCharset02".equalsIgnoreCase(charsetName)) {
- return new MockCharset("mockCharset00", new String[] {
- "mockCharset01", "mockCharset02" });
- }
- return null;
- }
+ public void test_forNameLjava_lang_String() {
+ // Invoke forName two times with the same canonical name.
+ // It should return the same reference.
+ Charset cs1 = Charset.forName("UTF-8");
+ Charset cs2 = Charset.forName("UTF-8");
+ assertSame(cs1, cs2);
- public Iterator charsets() {
- Vector v = new Vector();
- v.add(new MockCharset("mockCharset00", new String[] {
- "mockCharset01", "mockCharset02" }));
- return v.iterator();
- }
- }
+ // test forName: invoke forName two times for the same Charset using
+ // canonical name and alias, it should return the same reference.
+ Charset cs3 = Charset.forName("ASCII");
+ Charset cs4 = Charset.forName("US-ASCII");
+ assertSame(cs3, cs4);
+ }
+
+ static MockCharset charset1 = new MockCharset("mockCharset00",
+ new String[] { "mockCharset01", "mockCharset02" });
+
+ static MockCharset charset2 = new MockCharset("mockCharset10",
+ new String[] { "mockCharset11", "mockCharset12" });
+
+ // Test the required 6 charsets are supported.
+ public void testRequiredCharsetSupported() {
+ assertTrue(Charset.isSupported("US-ASCII"));
+ assertTrue(Charset.isSupported("ASCII"));
+ assertTrue(Charset.isSupported("ISO-8859-1"));
+ assertTrue(Charset.isSupported("ISO8859_1"));
+ assertTrue(Charset.isSupported("UTF-8"));
+ assertTrue(Charset.isSupported("UTF8"));
+ assertTrue(Charset.isSupported("UTF-16"));
+ assertTrue(Charset.isSupported("UTF-16BE"));
+ assertTrue(Charset.isSupported("UTF-16LE"));
+
+ Charset c1 = Charset.forName("US-ASCII");
+ assertEquals("US-ASCII", Charset.forName("US-ASCII").name());
+ assertEquals("US-ASCII", Charset.forName("ASCII").name());
+ assertEquals("ISO-8859-1", Charset.forName("ISO-8859-1").name());
+ assertEquals("ISO-8859-1", Charset.forName("ISO8859_1").name());
+ assertEquals("UTF-8", Charset.forName("UTF-8").name());
+ assertEquals("UTF-8", Charset.forName("UTF8").name());
+ assertEquals("UTF-16", Charset.forName("UTF-16").name());
+ assertEquals("UTF-16BE", Charset.forName("UTF-16BE").name());
+ assertEquals("UTF-16LE", Charset.forName("UTF-16LE").name());
+
+ assertNotSame(Charset.availableCharsets(), Charset.availableCharsets());
+ // assertSame(Charset.forName("US-ASCII"), Charset.availableCharsets().get("US-ASCII"));
+ // assertSame(Charset.forName("US-ASCII"), c1);
+ assertTrue(Charset.availableCharsets().containsKey("US-ASCII"));
+ assertTrue(Charset.availableCharsets().containsKey("ISO-8859-1"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-8"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-16"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-16BE"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-16LE"));
+ }
+
+ public void testIsSupported_Null() {
+ try {
+ Charset.isSupported(null);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testIsSupported_EmptyString() {
+ try {
+ Charset.isSupported("");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testIsSupported_InvalidInitialCharacter() {
+ try {
+ Charset.isSupported(".char");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testIsSupported_IllegalName() {
+ try {
+ Charset.isSupported(" ///#$$");
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ }
+
+ public void testIsSupported_NotSupported() {
+ assertFalse(Charset.isSupported("well-formed-name-of-a-charset-that-does-not-exist"));
+ }
+
+ public void testForName_Null() {
+ try {
+ Charset.forName(null);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testForName_EmptyString() {
+ try {
+ Charset.forName("");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testForName_InvalidInitialCharacter() {
+ try {
+ Charset.forName(".char");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testForName_IllegalName() {
+ try {
+ Charset.forName(" ///#$$");
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ }
+
+ public void testForName_NotSupported() {
+ try {
+ Charset.forName("impossible");
+ fail();
+ } catch (UnsupportedCharsetException expected) {
+ }
+ }
+
+ public void testConstructor_Normal() {
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ MockCharset c = new MockCharset(mockName, new String[] { "mock" });
+ assertEquals(mockName, c.name());
+ assertEquals(mockName, c.displayName());
+ assertEquals(mockName, c.displayName(Locale.getDefault()));
+ assertEquals("mock", c.aliases().toArray()[0]);
+ assertEquals(1, c.aliases().toArray().length);
+ }
+
+ public void testConstructor_EmptyCanonicalName() {
+ try {
+ new MockCharset("", new String[0]);
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ }
+
+ public void testConstructor_IllegalCanonicalName_Initial() {
+ try {
+ new MockCharset("-123", new String[] { "mock" });
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ }
+
+ public void testConstructor_IllegalCanonicalName_Middle() {
+ try {
+ new MockCharset("1%%23", new String[] { "mock" });
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ try {
+ new MockCharset("1//23", new String[] { "mock" });
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ }
+
+ public void testConstructor_NullCanonicalName() {
+ try {
+ MockCharset c = new MockCharset(null, new String[] { "mock" });
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testConstructor_NullAliases() {
+ MockCharset c = new MockCharset("mockChar", null);
+ assertEquals("mockChar", c.name());
+ assertEquals("mockChar", c.displayName());
+ assertEquals("mockChar", c.displayName(Locale.getDefault()));
+ assertEquals(0, c.aliases().toArray().length);
+ }
+
+ public void testConstructor_NullAliase() {
+ try {
+ new MockCharset("mockChar", new String[] { "mock", null });
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testConstructor_NoAliases() {
+ MockCharset c = new MockCharset("mockChar", new String[0]);
+ assertEquals("mockChar", c.name());
+ assertEquals("mockChar", c.displayName());
+ assertEquals("mockChar", c.displayName(Locale.getDefault()));
+ assertEquals(0, c.aliases().toArray().length);
+ }
+
+ public void testConstructor_EmptyAliases() {
+ try {
+ new MockCharset("mockChar", new String[] { "" });
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ }
+
+ // Test the constructor with illegal aliases: starting with neither a digit nor a letter.
+ public void testConstructor_IllegalAliases_Initial() {
+ try {
+ new MockCharset("mockChar", new String[] { "mock", "-123" });
+ fail();
+ } catch (IllegalCharsetNameException e) {
+ }
+ }
+
+ public void testConstructor_IllegalAliases_Middle() {
+ try {
+ new MockCharset("mockChar", new String[] { "mock", "22##ab" });
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ try {
+ new MockCharset("mockChar", new String[] { "mock", "22%%ab" });
+ fail();
+ } catch (IllegalCharsetNameException expected) {
+ }
+ }
+
+ public void testAliases_Multiple() {
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ MockCharset c = new MockCharset("mockChar", new String[] { "mock", mockName, "mock2" });
+ assertEquals("mockChar", c.name());
+ assertEquals(3, c.aliases().size());
+ assertTrue(c.aliases().contains("mock"));
+ assertTrue(c.aliases().contains(mockName));
+ assertTrue(c.aliases().contains("mock2"));
+
+ try {
+ c.aliases().clear();
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ public void testAliases_Duplicate() {
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ MockCharset c = new MockCharset("mockChar", new String[] { "mockChar",
+ "mock", mockName, "mock", "mockChar", "mock", "mock2" });
+ assertEquals("mockChar", c.name());
+ assertEquals(4, c.aliases().size());
+ assertTrue(c.aliases().contains("mockChar"));
+ assertTrue(c.aliases().contains("mock"));
+ assertTrue(c.aliases().contains(mockName));
+ assertTrue(c.aliases().contains("mock2"));
+ }
+
+ public void testCanEncode() {
+ MockCharset c = new MockCharset("mock", null);
+ assertTrue(c.canEncode());
+ }
+
+ public void testIsRegistered() {
+ MockCharset c = new MockCharset("mock", null);
+ assertTrue(c.isRegistered());
+ }
+
+ public void testDisplayName_Locale_Null() {
+ MockCharset c = new MockCharset("mock", null);
+ assertEquals("mock", c.displayName(null));
+ }
+
+ public void testCompareTo_Normal() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertEquals(0, c1.compareTo(c1));
+
+ MockCharset c2 = new MockCharset("Mock", null);
+ assertEquals(0, c1.compareTo(c2));
+
+ c2 = new MockCharset("mock2", null);
+ assertTrue(c1.compareTo(c2) < 0);
+ assertTrue(c2.compareTo(c1) > 0);
+
+ c2 = new MockCharset("mack", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+
+ c2 = new MockCharset("m.", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+
+ c2 = new MockCharset("m:", null);
+ assertEquals("mock".compareToIgnoreCase("m:"), c1.compareTo(c2));
+ assertEquals("m:".compareToIgnoreCase("mock"), c2.compareTo(c1));
+
+ c2 = new MockCharset("m-", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+
+ c2 = new MockCharset("m_", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+ }
+
+ public void testCompareTo_Null() {
+ MockCharset c1 = new MockCharset("mock", null);
+ try {
+ c1.compareTo(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testCompareTo_DiffCharsetClass() {
+ MockCharset c1 = new MockCharset("mock", null);
+ MockCharset2 c2 = new MockCharset2("Mock", new String[] { "myname" });
+ assertEquals(0, c1.compareTo(c2));
+ assertEquals(0, c2.compareTo(c1));
+ }
+
+ public void testEquals_Normal() {
+ MockCharset c1 = new MockCharset("mock", null);
+ MockCharset2 c2 = new MockCharset2("mock", null);
+ assertTrue(c1.equals(c2));
+ assertTrue(c2.equals(c1));
+
+ c2 = new MockCharset2("Mock", null);
+ assertFalse(c1.equals(c2));
+ assertFalse(c2.equals(c1));
+ }
+
+ public void testEquals_Null() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertFalse(c1.equals(null));
+ }
+
+ public void testEquals_NonCharsetObject() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertFalse(c1.equals("test"));
+ }
+
+ public void testEquals_DiffCharsetClass() {
+ MockCharset c1 = new MockCharset("mock", null);
+ MockCharset2 c2 = new MockCharset2("mock", null);
+ assertTrue(c1.equals(c2));
+ assertTrue(c2.equals(c1));
+ }
+
+ public void testHashCode_DiffCharsetClass() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertEquals(c1.hashCode(), "mock".hashCode());
+
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ c1 = new MockCharset(mockName, new String[] { "mockChar", "mock",
+ mockName, "mock", "mockChar", "mock", "mock2" });
+ assertEquals(mockName.hashCode(), c1.hashCode());
+ }
+
+ public void testEncode_CharBuffer_Normal() throws Exception {
+ MockCharset c1 = new MockCharset("testEncode_CharBuffer_Normal_mock", null);
+ ByteBuffer bb = c1.encode(CharBuffer.wrap("abcdefg"));
+ assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
+ bb = c1.encode(CharBuffer.wrap(""));
+ assertEquals("", new String(bb.array(), "iso8859-1"));
+ }
+
+ public void testEncode_CharBuffer_Unmappable() throws Exception {
+ Charset c1 = Charset.forName("iso8859-1");
+ ByteBuffer bb = c1.encode(CharBuffer.wrap("abcd\u5D14efg"));
+ assertEquals(new String(bb.array(), "iso8859-1"),
+ "abcd" + new String(c1.newEncoder().replacement(), "iso8859-1") + "efg");
+ }
+
+ public void testEncode_CharBuffer_NullCharBuffer() {
+ MockCharset c = new MockCharset("mock", null);
+ try {
+ c.encode((CharBuffer) null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testEncode_CharBuffer_NullEncoder() {
+ MockCharset2 c = new MockCharset2("mock2", null);
+ try {
+ c.encode(CharBuffer.wrap("hehe"));
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testEncode_String_Normal() throws Exception {
+ MockCharset c1 = new MockCharset("testEncode_String_Normal_mock", null);
+ ByteBuffer bb = c1.encode("abcdefg");
+ assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
+ bb = c1.encode("");
+ assertEquals("", new String(bb.array(), "iso8859-1"));
+ }
+
+ public void testEncode_String_Unmappable() throws Exception {
+ Charset c1 = Charset.forName("iso8859-1");
+ ByteBuffer bb = c1.encode("abcd\u5D14efg");
+ assertEquals(new String(bb.array(), "iso8859-1"),
+ "abcd" + new String(c1.newEncoder().replacement(), "iso8859-1") + "efg");
+ }
+
+ public void testEncode_String_NullString() {
+ MockCharset c = new MockCharset("mock", null);
+ try {
+ c.encode((String) null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testEncode_String_NullEncoder() {
+ MockCharset2 c = new MockCharset2("mock2", null);
+ try {
+ c.encode("hehe");
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testDecode_Normal() throws Exception {
+ MockCharset c1 = new MockCharset("mock", null);
+ CharBuffer cb = c1.decode(ByteBuffer.wrap("abcdefg".getBytes("iso8859-1")));
+ assertEquals("abcdefg", new String(cb.array()));
+ cb = c1.decode(ByteBuffer.wrap("".getBytes("iso8859-1")));
+ assertEquals("", new String(cb.array()));
+ }
+
+ public void testDecode_Malformed() throws Exception {
+ Charset c1 = Charset.forName("iso8859-1");
+ CharBuffer cb = c1.decode(ByteBuffer.wrap("abcd\u5D14efg".getBytes("iso8859-1")));
+ byte[] replacement = c1.newEncoder().replacement();
+ assertEquals(new String(cb.array()).trim(), "abcd" + new String(replacement, "iso8859-1") + "efg");
+ }
+
+ public void testDecode_NullByteBuffer() {
+ MockCharset c = new MockCharset("mock", null);
+ try {
+ c.decode(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testDecode_NullDecoder() {
+ MockCharset2 c = new MockCharset2("mock2", null);
+ try {
+ c.decode(ByteBuffer.wrap("hehe".getBytes()));
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testToString() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertTrue(-1 != c1.toString().indexOf("mock"));
+ }
+
+ static final class MockCharset extends Charset {
+ public MockCharset(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new MockDecoder(this);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockEncoder(this);
+ }
+ }
+
+ static class MockCharset2 extends Charset {
+ public MockCharset2(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return null;
+ }
+
+ public CharsetEncoder newEncoder() {
+ return null;
+ }
+ }
+
+ static class MockEncoder extends java.nio.charset.CharsetEncoder {
+ public MockEncoder(Charset cs) {
+ super(cs, 1, 3, new byte[] { (byte) '?' });
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ while (in.remaining() > 0) {
+ out.put((byte) in.get());
+ // out.put((byte) '!');
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+ static class MockDecoder extends java.nio.charset.CharsetDecoder {
+ public MockDecoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ while (in.remaining() > 0) {
+ out.put((char) in.get());
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+
+ // Test the method isSupported(String) with charset supported by multiple providers.
+ public void testIsSupported_And_ForName_NormalProvider() throws Exception {
+ assertTrue(Charset.isSupported("mockCharset10"));
+ // ignore case problem in mock, intended
+ assertTrue(Charset.isSupported("MockCharset11"));
+ assertTrue(Charset.isSupported("MockCharset12"));
+ assertTrue(Charset.isSupported("MOCKCharset10"));
+ // intended case problem in mock
+ assertTrue(Charset.isSupported("MOCKCharset11"));
+ assertTrue(Charset.isSupported("MOCKCharset12"));
+
+ assertTrue(Charset.forName("mockCharset10") instanceof MockCharset);
+ assertTrue(Charset.forName("mockCharset11") instanceof MockCharset);
+ assertTrue(Charset.forName("mockCharset12") instanceof MockCharset);
+
+ assertTrue(Charset.forName("mockCharset10") == charset2);
+ // intended case problem in mock
+ Charset.forName("mockCharset11");
+ assertTrue(Charset.forName("mockCharset12") == charset2);
+ }
+
+ // Test the method availableCharsets() with charset supported by multiple providers.
+ public void testAvailableCharsets_NormalProvider() throws Exception {
+ assertTrue(Charset.availableCharsets().containsKey("mockCharset00"));
+ assertTrue(Charset.availableCharsets().containsKey("MOCKCharset00"));
+ assertTrue(Charset.availableCharsets().get("mockCharset00") instanceof MockCharset);
+ assertTrue(Charset.availableCharsets().get("MOCKCharset00") instanceof MockCharset);
+ assertFalse(Charset.availableCharsets().containsKey("mockCharset01"));
+ assertFalse(Charset.availableCharsets().containsKey("mockCharset02"));
+
+ assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
+ assertTrue(Charset.availableCharsets().get("MOCKCharset10") == charset2);
+ assertFalse(Charset.availableCharsets().containsKey("mockCharset11"));
+ assertFalse(Charset.availableCharsets().containsKey("mockCharset12"));
+
+ assertTrue(Charset.availableCharsets().containsKey("mockCharset10"));
+ assertTrue(Charset.availableCharsets().containsKey("MOCKCharset10"));
+ assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
+ assertFalse(Charset.availableCharsets().containsKey("mockCharset11"));
+ assertFalse(Charset.availableCharsets().containsKey("mockCharset12"));
+ }
+
+ // Test the method forName(String) when the charset provider supports a
+ // built-in charset.
+ public void testForName_DuplicateWithBuiltInCharset() throws Exception {
+ assertFalse(Charset.forName("us-ascii") instanceof MockCharset);
+ assertFalse(Charset.availableCharsets().get("us-ascii") instanceof MockCharset);
+ }
+
+ public static class MockCharsetProvider extends CharsetProvider {
+ public Charset charsetForName(String charsetName) {
+ if ("MockCharset00".equalsIgnoreCase(charsetName) ||
+ "MockCharset01".equalsIgnoreCase(charsetName) ||
+ "MockCharset02".equalsIgnoreCase(charsetName)) {
+ return charset1;
+ } else if ("MockCharset10".equalsIgnoreCase(charsetName) ||
+ "MockCharset11".equalsIgnoreCase(charsetName) ||
+ "MockCharset12".equalsIgnoreCase(charsetName)) {
+ return charset2;
+ }
+ return null;
+ }
+
+ public Iterator charsets() {
+ Vector v = new Vector();
+ v.add(charset1);
+ v.add(charset2);
+ return v.iterator();
+ }
+ }
+
+ // Another mock charset provider attempting to provide the built-in charset "ascii" again.
+ public static class MockCharsetProviderASCII extends CharsetProvider {
+ public Charset charsetForName(String charsetName) {
+ if ("US-ASCII".equalsIgnoreCase(charsetName) || "ASCII".equalsIgnoreCase(charsetName)) {
+ return new MockCharset("US-ASCII", new String[] { "ASCII" });
+ }
+ return null;
+ }
+
+ public Iterator charsets() {
+ Vector v = new Vector();
+ v.add(new MockCharset("US-ASCII", new String[] { "ASCII" }));
+ return v.iterator();
+ }
+ }
}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
index 798a048..d483fcb 100644
--- a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
@@ -71,10 +71,8 @@
}
public void testSpecificDefaultValue() {
- assertEquals(1.1, encoder.averageBytesPerChar(), 0.0001);
- // assertEquals(2, encoder.averageBytesPerChar(), 0.0001);
- assertEquals(4, encoder.maxBytesPerChar(), 0);
- // assertEquals(3, encoder.maxBytesPerChar(), 0);
+ assertEquals(2, encoder.averageBytesPerChar(), 0);
+ assertEquals(3, encoder.maxBytesPerChar(), 0);
}
CharBuffer getMalformedCharBuffer() {
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
new file mode 100644
index 0000000..8f19e3a
--- /dev/null
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dalvik.system;
+
+/**
+ * Provides an interface to VM-global, Dalvik-specific features.
+ * An application cannot create its own Runtime instance, and must obtain
+ * one from the getRuntime method.
+ *
+ * @hide
+ */
+public final class VMRuntime {
+
+ /**
+ * Holds the VMRuntime singleton.
+ */
+ private static final VMRuntime THE_ONE = new VMRuntime();
+
+ /**
+ * Prevents this class from being instantiated.
+ */
+ private VMRuntime() {
+ }
+
+ /**
+ * Returns the object that represents the VM instance's Dalvik-specific
+ * runtime environment.
+ *
+ * @return the runtime object
+ */
+ public static VMRuntime getRuntime() {
+ return THE_ONE;
+ }
+
+ /**
+ * Returns a copy of the VM's command-line property settings.
+ * These are in the form "name=value" rather than "-Dname=value".
+ */
+ public native String[] properties();
+
+ /**
+ * Returns the VM's boot class path.
+ */
+ public native String bootClassPath();
+
+ /**
+ * Returns the VM's class path.
+ */
+ public native String classPath();
+
+ /**
+ * Returns the VM's version.
+ */
+ public native String vmVersion();
+
+ /**
+ * Returns the name of the shared library providing the VM implementation.
+ */
+ public native String vmLibrary();
+
+ /**
+ * Gets the current ideal heap utilization, represented as a number
+ * between zero and one. After a GC happens, the Dalvik heap may
+ * be resized so that (size of live objects) / (size of heap) is
+ * equal to this number.
+ *
+ * @return the current ideal heap utilization
+ */
+ public native float getTargetHeapUtilization();
+
+ /**
+ * Sets the current ideal heap utilization, represented as a number
+ * between zero and one. After a GC happens, the Dalvik heap may
+ * be resized so that (size of live objects) / (size of heap) is
+ * equal to this number.
+ *
+ * <p>This is only a hint to the garbage collector and may be ignored.
+ *
+ * @param newTarget the new suggested ideal heap utilization.
+ * This value may be adjusted internally.
+ * @return the previous ideal heap utilization
+ * @throws IllegalArgumentException if newTarget is <= 0.0 or >= 1.0
+ */
+ public float setTargetHeapUtilization(float newTarget) {
+ if (newTarget <= 0.0f || newTarget >= 1.0f) {
+ throw new IllegalArgumentException(newTarget +
+ " out of range (0,1)");
+ }
+ /* Synchronize to make sure that only one thread gets
+ * a given "old" value if both update at the same time.
+ * Allows for reliable save-and-restore semantics.
+ */
+ synchronized (this) {
+ float oldTarget = getTargetHeapUtilization();
+ nativeSetTargetHeapUtilization(newTarget);
+ return oldTarget;
+ }
+ }
+
+ /**
+ * Sets the target SDK version. Should only be called before the
+ * app starts to run, because it may change the VM's behavior in
+ * dangerous ways. Use 0 to mean "current" (since callers won't
+ * necessarily know the actual current SDK version, and the
+ * allocated version numbers start at 1).
+ */
+ public native void setTargetSdkVersion(int targetSdkVersion);
+
+ /**
+ * This method exists for binary compatibility. It was part of a
+ * heap sizing API which was removed in Android 3.0 (Honeycomb).
+ */
+ @Deprecated
+ public long getMinimumHeapSize() {
+ return 0;
+ }
+
+ /**
+ * This method exists for binary compatibility. It was part of a
+ * heap sizing API which was removed in Android 3.0 (Honeycomb).
+ */
+ @Deprecated
+ public long setMinimumHeapSize(long size) {
+ return 0;
+ }
+
+ /**
+ * This method exists for binary compatibility. It used to
+ * perform a garbage collection that cleared SoftReferences.
+ */
+ @Deprecated
+ public void gcSoftReferences() {}
+
+ /**
+ * This method exists for binary compatibility. It is equivalent
+ * to {@link System#runFinalization}.
+ */
+ @Deprecated
+ public void runFinalizationSync() {
+ System.runFinalization();
+ }
+
+ /**
+ * Implements setTargetHeapUtilization().
+ *
+ * @param newTarget the new suggested ideal heap utilization.
+ * This value may be adjusted internally.
+ */
+ private native void nativeSetTargetHeapUtilization(float newTarget);
+
+ /**
+ * This method exists for binary compatibility. It was part of
+ * the external allocation API which was removed in Android 3.0 (Honeycomb).
+ */
+ @Deprecated
+ public boolean trackExternalAllocation(long size) {
+ return true;
+ }
+
+ /**
+ * This method exists for binary compatibility. It was part of
+ * the external allocation API which was removed in Android 3.0 (Honeycomb).
+ */
+ @Deprecated
+ public void trackExternalFree(long size) {}
+
+ /**
+ * This method exists for binary compatibility. It was part of
+ * the external allocation API which was removed in Android 3.0 (Honeycomb).
+ */
+ @Deprecated
+ public long getExternalBytesAllocated() {
+ return 0;
+ }
+
+ /**
+ * Tells the VM to enable the JIT compiler. If the VM does not have a JIT
+ * implementation, calling this method should have no effect.
+ */
+ public native void startJitCompilation();
+
+ /**
+ * Tells the VM to disable the JIT compiler. If the VM does not have a JIT
+ * implementation, calling this method should have no effect.
+ */
+ public native void disableJitCompilation();
+
+ /**
+ * Returns an array allocated in an area of the Java heap where it will never be moved.
+ * This is used to implement native allocations on the Java heap, such as DirectByteBuffers
+ * and Bitmaps.
+ */
+ public native Object newNonMovableArray(Class<?> componentType, int length);
+
+ /**
+ * Returns the address of array[0]. This differs from using JNI in that JNI might lie and
+ * give you the address of a copy of the array when in forcecopy mode.
+ */
+ public native long addressOf(Object array);
+
+ /**
+ * Removes any growth limits, allowing the application to allocate
+ * up to the maximum heap size.
+ */
+ public native void clearGrowthLimit();
+
+ /**
+ * Returns true if either a Java debugger or native debugger is active.
+ */
+ public native boolean isDebuggerActive();
+
+ /**
+ * Registers a native allocation so that the heap knows about it and performs GC as required.
+ * If the number of native allocated bytes exceeds the native allocation watermark, the
+ * function requests a concurrent GC. If the native bytes allocated exceeds a second higher
+ * watermark, it is determined that the application is registering native allocations at an
+ * unusually high rate and a GC is performed inside of the function to prevent memory usage
+ * from excessively increasing.
+ */
+ public native void registerNativeAllocation(int bytes);
+
+ /**
+ * Registers a native free by reducing the number of native bytes accounted for.
+ */
+ public native void registerNativeFree(int bytes);
+
+ public native void trimHeap();
+ public native void concurrentGC();
+
+ public void preloadDexCaches() {
+ // Do nothing with ART, image generation already does this.
+ }
+}
diff --git a/libart/src/main/java/dalvik/system/VMStack.java b/libart/src/main/java/dalvik/system/VMStack.java
new file mode 100644
index 0000000..ee0a0db
--- /dev/null
+++ b/libart/src/main/java/dalvik/system/VMStack.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dalvik.system;
+
+/**
+ * Provides a limited interface to the Dalvik VM stack. This class is mostly
+ * used for implementing security checks.
+ *
+ * @hide
+ */
+public final class VMStack {
+ /**
+ * Returns the defining class loader of the caller's caller.
+ *
+ * @return the requested class loader, or {@code null} if this is the
+ * bootstrap class loader.
+ */
+ native public static ClassLoader getCallingClassLoader();
+
+ /**
+ * Returns the class of the caller's caller.
+ *
+ * @return the requested class, or {@code null}.
+ */
+ public static Class<?> getStackClass1() {
+ return getStackClass2();
+ }
+
+ /**
+ * Returns the class of the caller's caller's caller.
+ *
+ * @return the requested class, or {@code null}.
+ */
+ native public static Class<?> getStackClass2();
+
+ /**
+ * Returns the first ClassLoader on the call stack that isn't either of
+ * the passed-in ClassLoaders.
+ */
+ public native static ClassLoader getClosestUserClassLoader(ClassLoader bootstrap,
+ ClassLoader system);
+
+ /**
+ * Retrieves the stack trace from the specified thread.
+ *
+ * @param t
+ * thread of interest
+ * @return an array of stack trace elements, or null if the thread
+ * doesn't have a stack trace (e.g. because it exited)
+ */
+ native public static StackTraceElement[] getThreadStackTrace(Thread t);
+
+ /**
+ * Retrieves a partial stack trace from the specified thread into
+ * the provided array.
+ *
+ * @param t
+ * thread of interest
+ * @param stackTraceElements
+ * preallocated array for use when only the top of stack is
+ * desired. Unused elements will be filled with null values.
+ * @return the number of elements filled
+ */
+ native public static int fillStackTraceElements(Thread t,
+ StackTraceElement[] stackTraceElements);
+}
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
new file mode 100644
index 0000000..d1b9a18
--- /dev/null
+++ b/libart/src/main/java/java/lang/Class.java
@@ -0,0 +1,1756 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2006-2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+import com.android.dex.Dex;
+import dalvik.system.VMStack;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AbstractMethod;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.ArtField;
+import java.lang.reflect.ArtMethod;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.InternalNames;
+import libcore.reflect.Types;
+import libcore.util.BasicLruCache;
+import libcore.util.CollectionUtils;
+import libcore.util.EmptyArray;
+
+/**
+ * The in-memory representation of a Java class. This representation serves as
+ * the starting point for querying class-related information, a process usually
+ * called "reflection". There are basically three types of {@code Class}
+ * instances: those representing real classes and interfaces, those representing
+ * primitive types, and those representing array classes.
+ *
+ * <h4>Class instances representing object types (classes or interfaces)</h4>
+ * <p>
+ * These represent an ordinary class or interface as found in the class
+ * hierarchy. The name associated with these {@code Class} instances is simply
+ * the fully qualified class name of the class or interface that it represents.
+ * In addition to this human-readable name, each class is also associated by a
+ * so-called <em>descriptor</em>, which is the letter "L", followed by the
+ * class name and a semicolon (";"). The descriptor is what the runtime system
+ * uses internally for identifying the class (for example in a DEX file).
+ * </p>
+ * <h4>Classes representing primitive types</h4>
+ * <p>
+ * These represent the standard Java primitive types and hence share their
+ * names (for example "int" for the {@code int} primitive type). Although it is
+ * not possible to create new instances based on these {@code Class} instances,
+ * they are still useful for providing reflection information, and as the
+ * component type of array classes. There is one {@code Class} instance for each
+ * primitive type, and their descriptors are:
+ * </p>
+ * <ul>
+ * <li>{@code B} representing the {@code byte} primitive type</li>
+ * <li>{@code S} representing the {@code short} primitive type</li>
+ * <li>{@code I} representing the {@code int} primitive type</li>
+ * <li>{@code J} representing the {@code long} primitive type</li>
+ * <li>{@code F} representing the {@code float} primitive type</li>
+ * <li>{@code D} representing the {@code double} primitive type</li>
+ * <li>{@code C} representing the {@code char} primitive type</li>
+ * <li>{@code Z} representing the {@code boolean} primitive type</li>
+ * <li>{@code V} representing void function return values</li>
+ * </ul>
+ * <p>
+ * <h4>Classes representing array classes</h4>
+ * <p>
+ * These represent the classes of Java arrays. There is one such {@code Class}
+ * instance per combination of array leaf component type and arity (number of
+ * dimensions). In this case, the name associated with the {@code Class}
+ * consists of one or more left square brackets (one per dimension in the array)
+ * followed by the descriptor of the class representing the leaf component type,
+ * which can be either an object type or a primitive type. The descriptor of a
+ * {@code Class} representing an array type is the same as its name. Examples
+ * of array class descriptors are:
+ * </p>
+ * <ul>
+ * <li>{@code [I} representing the {@code int[]} type</li>
+ * <li>{@code [Ljava/lang/String;} representing the {@code String[]} type</li>
+ * <li>{@code [[[C} representing the {@code char[][][]} type (three dimensions!)</li>
+ * </ul>
+ */
+public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type {
+
+ private static final long serialVersionUID = 3206093459760846163L;
+
+ /** defining class loader, or NULL for the "bootstrap" system loader. */
+ private transient ClassLoader classLoader;
+
+ /**
+ * For array classes, the component class object for instanceof/checkcast (for String[][][],
+ * this will be String[][]). NULL for non-array classes.
+ */
+ private transient Class<?> componentType;
+ /**
+ * DexCache of resolved constant pool entries. Will be null for certain VM-generated classes
+ * e.g. arrays and primitive classes.
+ */
+ private transient DexCache dexCache;
+
+ /** static, private, and <init> methods. */
+ private transient ArtMethod[] directMethods;
+
+ /**
+ * Instance fields. These describe the layout of the contents of an Object. Note that only the
+ * fields directly declared by this class are listed in iFields; fields declared by a
+ * superclass are listed in the superclass's Class.iFields.
+ *
+ * All instance fields that refer to objects are guaranteed to be at the beginning of the field
+ * list. {@link Class#numReferenceInstanceFields} specifies the number of reference fields.
+ */
+ private transient ArtField[] iFields;
+
+ /**
+ * The interface table (iftable_) contains pairs of a interface class and an array of the
+ * interface methods. There is one pair per interface supported by this class. That
+ * means one pair for each interface we support directly, indirectly via superclass, or
+ * indirectly via a superinterface. This will be null if neither we nor our superclass
+ * implement any interfaces.
+ *
+ * Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()".
+ * Invoke faceObj.blah(), where "blah" is part of the Face interface. We can't easily use a
+ * single vtable.
+ *
+ * For every interface a concrete class implements, we create an array of the concrete vtable_
+ * methods for the methods in the interface.
+ */
+ private transient Object[] ifTable;
+
+ /** Lazily computed name of this class; always prefer calling getName(). */
+ private transient String name;
+
+ /** Static fields */
+ private transient ArtField[] sFields;
+
+ /** The superclass, or NULL if this is java.lang.Object, an interface or primitive type. */
+ private transient Class<? super T> superClass;
+
+ /** If class verify fails, we must return same error on subsequent tries. */
+ private transient Class<?> verifyErrorClass;
+
+ /** Virtual methods defined in this class; invoked through vtable. */
+ private transient ArtMethod[] virtualMethods;
+
+ /**
+ * Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass
+ * is copied in, and virtual methods from our class either replace those from the super or are
+ * appended. For abstract classes, methods may be created in the vtable that aren't in
+ * virtual_ methods_ for miranda methods.
+ */
+ private transient ArtMethod[] vtable;
+
+ /** access flags; low 16 bits are defined by VM spec */
+ private transient int accessFlags;
+
+ /**
+ * Total size of the Class instance; used when allocating storage on GC heap.
+ * See also {@link Class#objectSize}.
+ */
+ private transient int classSize;
+
+ /**
+ * tid used to check for recursive static initializer invocation.
+ */
+ private transient int clinitThreadId;
+
+ /**
+ * Class def index from dex file. An index of 65535 indicates that there is no class definition,
+ * for example for an array type.
+ * TODO: really 16bits as type indices are 16bit.
+ */
+ private transient int dexClassDefIndex;
+
+ /**
+ * Class type index from dex file, lazily computed. An index of 65535 indicates that the type
+ * index isn't known. Volatile to avoid double-checked locking bugs.
+ * TODO: really 16bits as type indices are 16bit.
+ */
+ private transient volatile int dexTypeIndex;
+
+ /** Number of instance fields that are object references. */
+ private transient int numReferenceInstanceFields;
+
+ /** Number of static fields that are object references. */
+ private transient int numReferenceStaticFields;
+
+ /**
+ * Total object size; used when allocating storage on GC heap. For interfaces and abstract
+ * classes this will be zero. See also {@link Class#classSize}.
+ */
+ private transient int objectSize;
+
+ /** Primitive type value, or 0 if not a primitive type; set for generated primitive classes. */
+ private transient int primitiveType;
+
+ /** Bitmap of offsets of iFields. */
+ private transient int referenceInstanceOffsets;
+
+ /** Bitmap of offsets of sFields. */
+ private transient int referenceStaticOffsets;
+
+ /** State of class initialization */
+ private transient int status;
+
+ private Class() {
+ // Prevent this class to be instantiated, instance should be created by JVM only
+ }
+
+ /**
+ * Returns a {@code Class} object which represents the class with
+ * the given name. The name should be the name of a non-primitive
+ * class, as described in the {@link Class class definition}.
+ * Primitive types can not be found using this method; use {@code
+ * int.class} or {@code Integer.TYPE} instead.
+ *
+ * <p>If the class has not yet been loaded, it is loaded and initialized
+ * first. This is done through either the class loader of the calling class
+ * or one of its parent class loaders. It is possible that a static initializer is run as
+ * a result of this call.
+ *
+ * @throws ClassNotFoundException
+ * if the requested class cannot be found.
+ * @throws LinkageError
+ * if an error occurs during linkage
+ * @throws ExceptionInInitializerError
+ * if an exception occurs during static initialization of a
+ * class.
+ */
+ public static Class<?> forName(String className) throws ClassNotFoundException {
+ return forName(className, true, VMStack.getCallingClassLoader());
+ }
+
+ /**
+ * Returns a {@code Class} object which represents the class with
+ * the given name. The name should be the name of a non-primitive
+ * class, as described in the {@link Class class definition}.
+ * Primitive types can not be found using this method; use {@code
+ * int.class} or {@code Integer.TYPE} instead.
+ *
+ * <p>If the class has not yet been loaded, it is loaded first, using the given class loader.
+ * If the class has not yet been initialized and {@code shouldInitialize} is true,
+ * the class will be initialized.
+ *
+ * @throws ClassNotFoundException
+ * if the requested class cannot be found.
+ * @throws LinkageError
+ * if an error occurs during linkage
+ * @throws ExceptionInInitializerError
+ * if an exception occurs during static initialization of a
+ * class.
+ */
+ public static Class<?> forName(String className, boolean shouldInitialize,
+ ClassLoader classLoader) throws ClassNotFoundException {
+
+ if (classLoader == null) {
+ classLoader = ClassLoader.getSystemClassLoader();
+ }
+ // Catch an Exception thrown by the underlying native code. It wraps
+ // up everything inside a ClassNotFoundException, even if e.g. an
+ // Error occurred during initialization. This as a workaround for
+ // an ExceptionInInitializerError that's also wrapped. It is actually
+ // expected to be thrown. Maybe the same goes for other errors.
+ // Not wrapping up all the errors will break android though.
+ Class<?> result;
+ try {
+ result = classForName(className, shouldInitialize, classLoader);
+ } catch (ClassNotFoundException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof LinkageError) {
+ throw (LinkageError) cause;
+ }
+ throw e;
+ }
+ return result;
+ }
+
+ static native Class<?> classForName(String className, boolean shouldInitialize,
+ ClassLoader classLoader) throws ClassNotFoundException;
+
+ /**
+ * Returns an array containing {@code Class} objects for all
+ * public classes, interfaces, enums and annotations that are
+ * members of this class and its superclasses. This does not
+ * include classes of implemented interfaces. If there are no
+ * such class members or if this object represents a primitive
+ * type then an array of length 0 is returned.
+ */
+ public Class<?>[] getClasses() {
+ List<Class<?>> result = new ArrayList<Class<?>>();
+ for (Class<?> c = this; c != null; c = c.superClass) {
+ for (Class<?> member : c.getDeclaredClasses()) {
+ if (Modifier.isPublic(member.getModifiers())) {
+ result.add(member);
+ }
+ }
+ }
+ return result.toArray(new Class[result.size()]);
+ }
+
+ @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+ return AnnotationAccess.getAnnotation(this, annotationType);
+ }
+
+ /**
+ * Returns an array containing all the annotations of this class. If there are no annotations
+ * then an empty array is returned.
+ *
+ * @see #getDeclaredAnnotations()
+ */
+ @Override public Annotation[] getAnnotations() {
+ return AnnotationAccess.getAnnotations(this);
+ }
+
+ /**
+ * Returns the canonical name of this class. If this class does not have a
+ * canonical name as defined in the Java Language Specification, then the
+ * method returns {@code null}.
+ */
+ public String getCanonicalName() {
+ if (isLocalClass() || isAnonymousClass())
+ return null;
+
+ if (isArray()) {
+ /*
+ * The canonical name of an array type depends on the (existence of)
+ * the component type's canonical name.
+ */
+ String name = getComponentType().getCanonicalName();
+ if (name != null) {
+ return name + "[]";
+ }
+ } else if (isMemberClass()) {
+ /*
+ * The canonical name of an inner class depends on the (existence
+ * of) the declaring class' canonical name.
+ */
+ String name = getDeclaringClass().getCanonicalName();
+ if (name != null) {
+ return name + "." + getSimpleName();
+ }
+ } else {
+ /*
+ * The canonical name of a top-level class or primitive type is
+ * equal to the fully qualified name.
+ */
+ return getName();
+ }
+
+ /*
+ * Other classes don't have a canonical name.
+ */
+ return null;
+ }
+
+ /**
+ * Returns the class loader which was used to load the class represented by
+ * this {@code Class}. Implementations are free to return {@code null} for
+ * classes that were loaded by the bootstrap class loader. The Android
+ * reference implementation, though, always returns a reference to an actual
+ * class loader.
+ */
+ public ClassLoader getClassLoader() {
+ if (this.isPrimitive()) {
+ return null;
+ }
+
+ ClassLoader loader = getClassLoaderImpl();
+ if (loader == null) {
+ loader = BootClassLoader.getInstance();
+ }
+ return loader;
+ }
+
+ /**
+ * This must be provided by the VM vendor, as it is used by other provided
+ * class implementations in this package. Outside of this class, it is used
+ * by SecurityManager.classLoaderDepth(),
+ * currentClassLoader() and currentLoadedClass(). Return the ClassLoader for
+ * this Class without doing any security checks. The bootstrap ClassLoader
+ * is returned, unlike getClassLoader() which returns null in place of the
+ * bootstrap ClassLoader.
+ */
+ ClassLoader getClassLoaderImpl() {
+ ClassLoader loader = classLoader;
+ return loader == null ? BootClassLoader.getInstance() : loader;
+ }
+
+ /**
+ * Returns a {@code Class} object which represents the component type if
+ * this class represents an array type. Returns {@code null} if this class
+ * does not represent an array type. The component type of an array type is
+ * the type of the elements of the array.
+ */
+ public Class<?> getComponentType() {
+ return componentType;
+ }
+
+ /**
+ * Returns the dex file from which this class was loaded.
+ *
+ * @hide
+ */
+ public Dex getDex() {
+ if (dexCache == null) {
+ return null;
+ }
+ return dexCache.getDex();
+ }
+
+ /**
+ * Returns a string from the dex cache, computing the string from the dex file if necessary.
+ *
+ * @hide
+ */
+ public String getDexCacheString(Dex dex, int dexStringIndex) {
+ String[] dexCacheStrings = dexCache.strings;
+ String s = dexCacheStrings[dexStringIndex];
+ if (s == null) {
+ s = dex.strings().get(dexStringIndex).intern();
+ dexCacheStrings[dexStringIndex] = s;
+ }
+ return s;
+ }
+
+ /**
+ * Returns a resolved type from the dex cache, computing the type from the dex file if
+ * necessary.
+ *
+ * @hide
+ */
+ public Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
+ Class<?>[] dexCacheResolvedTypes = dexCache.resolvedTypes;
+ Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex];
+ if (resolvedType == null) {
+ int descriptorIndex = dex.typeIds().get(dexTypeIndex);
+ String descriptor = getDexCacheString(dex, descriptorIndex);
+ resolvedType = InternalNames.getClass(getClassLoader(), descriptor);
+ dexCacheResolvedTypes[dexTypeIndex] = resolvedType;
+ }
+ return resolvedType;
+ }
+
+ /**
+ * Returns a {@code Constructor} object which represents the public
+ * constructor matching the given parameter types.
+ * {@code (Class[]) null} is equivalent to the empty array.
+ *
+ * @throws NoSuchMethodException
+ * if the constructor cannot be found.
+ * @see #getDeclaredConstructor(Class[])
+ */
+ public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException {
+ return getConstructor(parameterTypes, true);
+ }
+
+ /**
+ * Returns a {@code Constructor} object which represents the constructor
+ * matching the specified parameter types that is declared by the class
+ * represented by this {@code Class}.
+ * {@code (Class[]) null} is equivalent to the empty array.
+ *
+ * @throws NoSuchMethodException
+ * if the requested constructor cannot be found.
+ * @see #getConstructor(Class[])
+ */
+ public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
+ throws NoSuchMethodException {
+ return getConstructor(parameterTypes, false);
+ }
+
+ /**
+ * Returns a constructor with the given parameters.
+ *
+ * @param publicOnly true to only return public constructores.
+ * @param parameterTypes argument types to match the constructor's.
+ */
+ private Constructor<T> getConstructor(Class<?>[] parameterTypes, boolean publicOnly)
+ throws NoSuchMethodException {
+ if (parameterTypes == null) {
+ parameterTypes = EmptyArray.CLASS;
+ }
+ for (Class<?> c : parameterTypes) {
+ if (c == null) {
+ throw new NoSuchMethodException("parameter type is null");
+ }
+ }
+ Constructor<T> result = getDeclaredConstructorInternal(parameterTypes);
+ if (result == null || publicOnly && !Modifier.isPublic(result.getAccessFlags())) {
+ throw new NoSuchMethodException("<init> " + Arrays.toString(parameterTypes));
+ }
+ return result;
+ }
+
+ /**
+ * Returns the constructor with the given parameters if it is defined by this class; null
+ * otherwise. This may return a non-public member.
+ *
+ * @param args the types of the parameters to the constructor.
+ */
+ private Constructor<T> getDeclaredConstructorInternal(Class<?>[] args) {
+ if (directMethods != null) {
+ for (ArtMethod m : directMethods) {
+ int modifiers = m.getAccessFlags();
+ if (Modifier.isStatic(modifiers)) {
+ // skip <clinit> which is a static constructor
+ continue;
+ }
+ if (!Modifier.isConstructor(modifiers)) {
+ continue;
+ }
+ if (!ArtMethod.equalConstructorParameters(m, args)) {
+ continue;
+ }
+ return new Constructor<T>(m);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns an array containing {@code Constructor} objects for all public
+ * constructors for this {@code Class}. If there
+ * are no public constructors or if this {@code Class} represents an array
+ * class, a primitive type or void then an empty array is returned.
+ *
+ * @see #getDeclaredConstructors()
+ */
+ public Constructor<?>[] getConstructors() {
+ ArrayList<Constructor<T>> constructors = new ArrayList();
+ getDeclaredConstructors(true, constructors);
+ return constructors.toArray(new Constructor[constructors.size()]);
+ }
+
+ /**
+ * Returns an array containing {@code Constructor} objects for all
+ * constructors declared in the class represented by this {@code Class}. If
+ * there are no constructors or if this {@code Class} represents an array
+ * class, a primitive type or void then an empty array is returned.
+ *
+ * @see #getConstructors()
+ */
+ public Constructor<?>[] getDeclaredConstructors() {
+ ArrayList<Constructor<T>> constructors = new ArrayList();
+ getDeclaredConstructors(false, constructors);
+ return constructors.toArray(new Constructor[constructors.size()]);
+ }
+
+ private void getDeclaredConstructors(boolean publicOnly, List<Constructor<T>> constructors) {
+ if (directMethods != null) {
+ for (ArtMethod m : directMethods) {
+ int modifiers = m.getAccessFlags();
+ if (!publicOnly || Modifier.isPublic(modifiers)) {
+ if (Modifier.isStatic(modifiers)) {
+ // skip <clinit> which is a static constructor
+ continue;
+ }
+ if (Modifier.isConstructor(modifiers)) {
+ constructors.add(new Constructor<T>(m));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a {@code Method} object which represents the method matching the
+ * specified name and parameter types that is declared by the class
+ * represented by this {@code Class}.
+ *
+ * @param name
+ * the requested method's name.
+ * @param parameterTypes
+ * the parameter types of the requested method.
+ * {@code (Class[]) null} is equivalent to the empty array.
+ * @return the method described by {@code name} and {@code parameterTypes}.
+ * @throws NoSuchMethodException
+ * if the requested constructor cannot be found.
+ * @throws NullPointerException
+ * if {@code name} is {@code null}.
+ * @see #getMethod(String, Class[])
+ */
+ public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
+ throws NoSuchMethodException {
+ return getMethod(name, parameterTypes, false);
+ }
+
+ /**
+ * Returns a {@code Method} object which represents the public method with
+ * the specified name and parameter types.
+ * {@code (Class[]) null} is equivalent to the empty array.
+ * This method first searches the
+ * class C represented by this {@code Class}, then the superclasses of C and
+ * finally the interfaces implemented by C and finally the superclasses of C
+ * for a method with matching name.
+ *
+ * @throws NoSuchMethodException
+ * if the method cannot be found.
+ * @see #getDeclaredMethod(String, Class[])
+ */
+ public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
+ return getMethod(name, parameterTypes, true);
+ }
+
+ private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
+ throws NoSuchMethodException {
+ if (name == null) {
+ throw new NullPointerException("name == null");
+ }
+ if (parameterTypes == null) {
+ parameterTypes = EmptyArray.CLASS;
+ }
+ for (Class<?> c : parameterTypes) {
+ if (c == null) {
+ throw new NoSuchMethodException("parameter type is null");
+ }
+ }
+ Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
+ : getDeclaredMethodInternal(name, parameterTypes);
+ // Fail if we didn't find the method or it was expected to be public.
+ if (result == null ||
+ (recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
+ throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
+ }
+ return result;
+ }
+
+ private Method getPublicMethodRecursive(String name, Class<?>[] parameterTypes) {
+ // search superclasses
+ for (Class<?> c = this; c != null; c = c.getSuperclass()) {
+ Method result = c.getDeclaredMethodInternal(name, parameterTypes);
+ if (result != null && Modifier.isPublic(result.getAccessFlags())) {
+ return result;
+ }
+ }
+ // search iftable which has a flattened and uniqued list of interfaces
+ Object[] iftable = ifTable;
+ if (iftable != null) {
+ for (int i = 0; i < iftable.length; i += 2) {
+ Class<?> ifc = (Class<?>) iftable[i];
+ Method result = ifc.getPublicMethodRecursive(name, parameterTypes);
+ if (result != null && Modifier.isPublic(result.getAccessFlags())) {
+ return result;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the method if it is defined by this class; null otherwise. This may return a
+ * non-public member.
+ *
+ * @param name the method name
+ * @param args the method's parameter types
+ */
+ private Method getDeclaredMethodInternal(String name, Class<?>[] args) {
+ // Covariant return types permit the class to define multiple
+ // methods with the same name and parameter types. Prefer to
+ // return a non-synthetic method in such situations. We may
+ // still return a synthetic method to handle situations like
+ // escalated visibility. We never return miranda methods that
+ // were synthesized by the VM.
+ int skipModifiers = Modifier.MIRANDA | Modifier.SYNTHETIC;
+ ArtMethod artMethodResult = null;
+ if (virtualMethods != null) {
+ for (ArtMethod m : virtualMethods) {
+ String methodName = ArtMethod.getMethodName(m);
+ if (!name.equals(methodName)) {
+ continue;
+ }
+ if (!ArtMethod.equalMethodParameters(m, args)) {
+ continue;
+ }
+ int modifiers = m.getAccessFlags();
+ if ((modifiers & skipModifiers) == 0) {
+ return new Method(m);
+ }
+ if ((modifiers & Modifier.MIRANDA) == 0) {
+ // Remember as potential result if it's not a miranda method.
+ artMethodResult = m;
+ }
+ }
+ }
+ if (artMethodResult == null) {
+ if (directMethods != null) {
+ for (ArtMethod m : directMethods) {
+ int modifiers = m.getAccessFlags();
+ if (Modifier.isConstructor(modifiers)) {
+ continue;
+ }
+ String methodName = ArtMethod.getMethodName(m);
+ if (!name.equals(methodName)) {
+ continue;
+ }
+ if (!ArtMethod.equalMethodParameters(m, args)) {
+ continue;
+ }
+ if ((modifiers & skipModifiers) == 0) {
+ return new Method(m);
+ }
+ // Direct methods cannot be miranda methods,
+ // so this potential result must be synthetic.
+ artMethodResult = m;
+ }
+ }
+ }
+ if (artMethodResult == null) {
+ return null;
+ }
+ return new Method(artMethodResult);
+ }
+
+ /**
+ * Returns an array containing {@code Method} objects for all methods
+ * declared in the class represented by this {@code Class}. If there are no
+ * methods or if this {@code Class} represents an array class, a primitive
+ * type or void then an empty array is returned.
+ *
+ * @see #getMethods()
+ */
+ public Method[] getDeclaredMethods() {
+ int initial_size = virtualMethods == null ? 0 : virtualMethods.length;
+ initial_size += directMethods == null ? 0 : directMethods.length;
+ ArrayList<Method> methods = new ArrayList<Method>(initial_size);
+ getDeclaredMethods(false, methods);
+ Method[] result = methods.toArray(new Method[methods.size()]);
+ for (Method m : result) {
+ // Throw NoClassDefFoundError if types cannot be resolved.
+ m.getReturnType();
+ m.getParameterTypes();
+ }
+ return result;
+
+ }
+
+ /**
+ * Returns the list of methods without performing any security checks
+ * first. If no methods exist, an empty array is returned.
+ */
+ private void getDeclaredMethods(boolean publicOnly, List<Method> methods) {
+ if (virtualMethods != null) {
+ for (ArtMethod m : virtualMethods) {
+ int modifiers = m.getAccessFlags();
+ if (!publicOnly || Modifier.isPublic(modifiers)) {
+ // Add non-miranda virtual methods.
+ if ((modifiers & Modifier.MIRANDA) == 0) {
+ methods.add(new Method(m));
+ }
+ }
+ }
+ }
+ if (directMethods != null) {
+ for (ArtMethod m : directMethods) {
+ int modifiers = m.getAccessFlags();
+ if (!publicOnly || Modifier.isPublic(modifiers)) {
+ // Add non-constructor direct/static methods.
+ if (!Modifier.isConstructor(modifiers)) {
+ methods.add(new Method(m));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns an array containing {@code Method} objects for all public methods
+ * for the class C represented by this {@code Class}. Methods may be
+ * declared in C, the interfaces it implements or in the superclasses of C.
+ * The elements in the returned array are in no particular order.
+ *
+ * <p>If there are no public methods or if this {@code Class} represents a
+ * primitive type or {@code void} then an empty array is returned.
+ *
+ * @see #getDeclaredMethods()
+ */
+ public Method[] getMethods() {
+ List<Method> methods = new ArrayList<Method>();
+ getPublicMethodsInternal(methods);
+ /*
+ * Remove duplicate methods defined by superclasses and
+ * interfaces, preferring to keep methods declared by derived
+ * types.
+ */
+ CollectionUtils.removeDuplicates(methods, Method.ORDER_BY_SIGNATURE);
+ return methods.toArray(new Method[methods.size()]);
+ }
+
+ /**
+ * Populates {@code result} with public methods defined by this class, its
+ * superclasses, and all implemented interfaces, including overridden methods.
+ */
+ private void getPublicMethodsInternal(List<Method> result) {
+ getDeclaredMethods(true, result);
+ if (!isInterface()) {
+ // Search superclasses, for interfaces don't search java.lang.Object.
+ for (Class<?> c = superClass; c != null; c = c.superClass) {
+ c.getDeclaredMethods(true, result);
+ }
+ }
+ // Search iftable which has a flattened and uniqued list of interfaces.
+ Object[] iftable = ifTable;
+ if (iftable != null) {
+ for (int i = 0; i < iftable.length; i += 2) {
+ Class<?> ifc = (Class<?>) iftable[i];
+ ifc.getDeclaredMethods(true, result);
+ }
+ }
+ }
+
+ /**
+ * Returns the annotations that are directly defined on the class
+ * represented by this {@code Class}. Annotations that are inherited are not
+ * included in the result. If there are no annotations at all, an empty
+ * array is returned.
+ *
+ * @see #getAnnotations()
+ */
+ @Override public Annotation[] getDeclaredAnnotations() {
+ List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
+ return result.toArray(new Annotation[result.size()]);
+ }
+
+ /**
+ * Returns an array containing {@code Class} objects for all classes,
+ * interfaces, enums and annotations that are members of this class.
+ */
+ public Class<?>[] getDeclaredClasses() {
+ return AnnotationAccess.getMemberClasses(this);
+ }
+
+ /**
+ * Returns a {@code Field} object for the field with the given name
+ * which is declared in the class represented by this {@code Class}.
+ *
+ * @throws NoSuchFieldException if the requested field can not be found.
+ * @see #getField(String)
+ */
+ public Field getDeclaredField(String name) throws NoSuchFieldException {
+ if (name == null) {
+ throw new NullPointerException("name == null");
+ }
+ Field result = getDeclaredFieldInternal(name);
+ if (result == null) {
+ throw new NoSuchFieldException(name);
+ } else {
+ result.getType(); // Throw NoClassDefFoundError if type cannot be resolved.
+ }
+ return result;
+ }
+
+ /**
+ * Returns an array containing {@code Field} objects for all fields declared
+ * in the class represented by this {@code Class}. If there are no fields or
+ * if this {@code Class} represents an array class, a primitive type or void
+ * then an empty array is returned.
+ *
+ * @see #getFields()
+ */
+ public Field[] getDeclaredFields() {
+ int initial_size = sFields == null ? 0 : sFields.length;
+ initial_size += iFields == null ? 0 : iFields.length;
+ ArrayList<Field> fields = new ArrayList(initial_size);
+ getDeclaredFields(false, fields);
+ Field[] result = fields.toArray(new Field[fields.size()]);
+ for (Field f : result) {
+ f.getType(); // Throw NoClassDefFoundError if type cannot be resolved.
+ }
+ return result;
+ }
+
+ private void getDeclaredFields(boolean publicOnly, List<Field> fields) {
+ if (iFields != null) {
+ for (ArtField f : iFields) {
+ if (!publicOnly || Modifier.isPublic(f.getAccessFlags())) {
+ fields.add(new Field(f));
+ }
+ }
+ }
+ if (sFields != null) {
+ for (ArtField f : sFields) {
+ if (!publicOnly || Modifier.isPublic(f.getAccessFlags())) {
+ fields.add(new Field(f));
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the field if it is defined by this class; null otherwise. This
+ * may return a non-public member.
+ */
+ private Field getDeclaredFieldInternal(String name) {
+ if (iFields != null) {
+ for (ArtField f : iFields) {
+ if (f.getName().equals(name)) {
+ return new Field(f);
+ }
+ }
+ }
+ if (sFields != null) {
+ for (ArtField f : sFields) {
+ if (f.getName().equals(name)) {
+ return new Field(f);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the class that this class is a member of, or {@code null} if this
+ * class is a top-level class, a primitive, an array, or defined within a
+ * method or constructor.
+ */
+ public Class<?> getDeclaringClass() {
+ return AnnotationAccess.getDeclaringClass(this);
+ }
+
+ /**
+ * Returns the class enclosing this class. For most classes this is the same
+ * as the {@link #getDeclaringClass() declaring class}. For classes defined
+ * within a method or constructor (typically anonymous inner classes), this
+ * is the declaring class of that member.
+ */
+ public Class<?> getEnclosingClass() {
+ Class<?> declaringClass = getDeclaringClass();
+ if (declaringClass != null) {
+ return declaringClass;
+ }
+ AccessibleObject member = AnnotationAccess.getEnclosingMethodOrConstructor(this);
+ return member != null
+ ? ((Member) member).getDeclaringClass()
+ : null;
+ }
+
+ /**
+ * Returns the enclosing {@code Constructor} of this {@code Class}, if it is an
+ * anonymous or local/automatic class; otherwise {@code null}.
+ */
+ public Constructor<?> getEnclosingConstructor() {
+ if (classNameImpliesTopLevel()) {
+ return null;
+ }
+ AccessibleObject result = AnnotationAccess.getEnclosingMethodOrConstructor(this);
+ return result instanceof Constructor ? (Constructor<?>) result : null;
+ }
+
+ /**
+ * Returns the enclosing {@code Method} of this {@code Class}, if it is an
+ * anonymous or local/automatic class; otherwise {@code null}.
+ */
+ public Method getEnclosingMethod() {
+ if (classNameImpliesTopLevel()) {
+ return null;
+ }
+ AccessibleObject result = AnnotationAccess.getEnclosingMethodOrConstructor(this);
+ return result instanceof Method ? (Method) result : null;
+ }
+
+ /**
+ * Returns true if this class is definitely a top level class, or false if
+ * a more expensive check like {@link #getEnclosingClass()} is necessary.
+ *
+ * <p>This is a hack that exploits an implementation detail of all Java
+ * language compilers: generated names always contain "$". As it is possible
+ * for a top level class to be named with a "$", a false result <strong>does
+ * not</strong> indicate that this isn't a top-level class.
+ */
+ private boolean classNameImpliesTopLevel() {
+ return !getName().contains("$");
+ }
+
+ /**
+ * Returns the {@code enum} constants associated with this {@code Class}.
+ * Returns {@code null} if this {@code Class} does not represent an {@code
+ * enum} type.
+ */
+ @SuppressWarnings("unchecked") // we only cast after confirming that this class is an enum
+ public T[] getEnumConstants() {
+ if (!isEnum()) {
+ return null;
+ }
+ return (T[]) Enum.getSharedConstants((Class) this).clone();
+ }
+
+ /**
+ * Returns a {@code Field} object which represents the public field with the
+ * given name. This method first searches the class C represented by
+ * this {@code Class}, then the interfaces implemented by C and finally the
+ * superclasses of C.
+ *
+ * @throws NoSuchFieldException
+ * if the field cannot be found.
+ * @see #getDeclaredField(String)
+ */
+ public Field getField(String name) throws NoSuchFieldException {
+ if (name == null) {
+ throw new NullPointerException("name == null");
+ }
+ Field result = getPublicFieldRecursive(name);
+ if (result == null) {
+ throw new NoSuchFieldException(name);
+ } else {
+ result.getType(); // Throw NoClassDefFoundError if type cannot be resolved.
+ }
+ return result;
+ }
+
+ private Field getPublicFieldRecursive(String name) {
+ // search superclasses
+ for (Class<?> c = this; c != null; c = c.superClass) {
+ Field result = c.getDeclaredFieldInternal(name);
+ if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
+ return result;
+ }
+ }
+
+ // search iftable which has a flattened and uniqued list of interfaces
+ if (ifTable != null) {
+ for (int i = 0; i < ifTable.length; i += 2) {
+ Class<?> ifc = (Class<?>) ifTable[i];
+ Field result = ifc.getPublicFieldRecursive(name);
+ if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
+ return result;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns an array containing {@code Field} objects for all public fields
+ * for the class C represented by this {@code Class}. Fields may be declared
+ * in C, the interfaces it implements or in the superclasses of C. The
+ * elements in the returned array are in no particular order.
+ *
+ * <p>If there are no public fields or if this class represents an array class,
+ * a primitive type or {@code void} then an empty array is returned.
+ *
+ * @see #getDeclaredFields()
+ */
+ public Field[] getFields() {
+ List<Field> fields = new ArrayList<Field>();
+ getPublicFieldsRecursive(fields);
+ Field[] result = fields.toArray(new Field[fields.size()]);
+ for (Field f : result) {
+ f.getType(); // Throw NoClassDefFoundError if type cannot be resolved.
+ }
+ return result;
+ }
+
+ /**
+ * Populates {@code result} with public fields defined by this class, its
+ * superclasses, and all implemented interfaces.
+ */
+ private void getPublicFieldsRecursive(List<Field> result) {
+ // search superclasses
+ for (Class<?> c = this; c != null; c = c.superClass) {
+ c.getDeclaredFields(true, result);
+ }
+
+ // search iftable which has a flattened and uniqued list of interfaces
+ Object[] iftable = ifTable;
+ if (iftable != null) {
+ for (int i = 0; i < iftable.length; i += 2) {
+ Class<?> ifc = (Class<?>) iftable[i];
+ ifc.getDeclaredFields(true, result);
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link Type}s of the interfaces that this {@code Class} directly
+ * implements. If the {@code Class} represents a primitive type or {@code
+ * void} then an empty array is returned.
+ */
+ public Type[] getGenericInterfaces() {
+ Type[] result;
+ synchronized (Caches.genericInterfaces) {
+ result = Caches.genericInterfaces.get(this);
+ if (result == null) {
+ String annotationSignature = AnnotationAccess.getSignature(this);
+ if (annotationSignature == null) {
+ result = getInterfaces();
+ } else {
+ GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
+ parser.parseForClass(this, annotationSignature);
+ result = Types.getTypeArray(parser.interfaceTypes, false);
+ }
+ Caches.genericInterfaces.put(this, result);
+ }
+ }
+ return (result.length == 0) ? result : result.clone();
+ }
+
+ /**
+ * Returns the {@code Type} that represents the superclass of this {@code
+ * class}.
+ */
+ public Type getGenericSuperclass() {
+ Type genericSuperclass = getSuperclass();
+ String annotationSignature = AnnotationAccess.getSignature(this);
+ if (annotationSignature != null) {
+ GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
+ parser.parseForClass(this, annotationSignature);
+ genericSuperclass = parser.superclassType;
+ }
+ return Types.getType(genericSuperclass);
+ }
+
+ /**
+ * Returns an array of {@code Class} objects that match the interfaces
+ * in the {@code implements} declaration of the class represented
+ * by this {@code Class}. The order of the elements in the array is
+ * identical to the order in the original class declaration. If the class
+ * does not implement any interfaces, an empty array is returned.
+ *
+ * <p>This method only returns directly-implemented interfaces, and does not
+ * include interfaces implemented by superclasses or superinterfaces of any
+ * implemented interfaces.
+ */
+ public Class<?>[] getInterfaces() {
+ if (isArray()) {
+ return new Class<?>[] { Cloneable.class, Serializable.class };
+ } else if (isProxy()) {
+ return getProxyInterfaces();
+ }
+ Dex dex = getDex();
+ if (dex == null) {
+ return EmptyArray.CLASS;
+ }
+ short[] interfaces = dex.interfaceTypeIndicesFromClassDefIndex(dexClassDefIndex);
+ Class<?>[] result = new Class<?>[interfaces.length];
+ for (int i = 0; i < interfaces.length; i++) {
+ result[i] = getDexCacheType(dex, interfaces[i]);
+ }
+ return result;
+ }
+
+ // Returns the interfaces that this proxy class directly implements.
+ private native Class<?>[] getProxyInterfaces();
+
+ /**
+ * Returns an integer that represents the modifiers of the class represented
+ * by this {@code Class}. The returned value is a combination of bits
+ * defined by constants in the {@link Modifier} class.
+ */
+ public int getModifiers() {
+ // Array classes inherit modifiers from their component types, but in the case of arrays
+ // of an inner class, the class file may contain "fake" access flags because it's not valid
+ // for a top-level class to private, say. The real access flags are stored in the InnerClass
+ // attribute, so we need to make sure we drill down to the inner class: the accessFlags
+ // field is not the value we want to return, and the synthesized array class does not itself
+ // have an InnerClass attribute. https://code.google.com/p/android/issues/detail?id=56267
+ if (isArray()) {
+ int componentModifiers = getComponentType().getModifiers();
+ if ((componentModifiers & Modifier.INTERFACE) != 0) {
+ componentModifiers &= ~(Modifier.INTERFACE | Modifier.STATIC);
+ }
+ return Modifier.ABSTRACT | Modifier.FINAL | componentModifiers;
+ }
+ int JAVA_FLAGS_MASK = 0xffff;
+ int modifiers = AnnotationAccess.getInnerClassFlags(this, accessFlags & JAVA_FLAGS_MASK);
+ return modifiers & JAVA_FLAGS_MASK;
+ }
+
+ /**
+ * Returns the name of the class represented by this {@code Class}. For a
+ * description of the format which is used, see the class definition of
+ * {@link Class}.
+ */
+ public String getName() {
+ String result = name;
+ return (result == null) ? (name = getNameNative()) : result;
+ }
+
+ private native String getNameNative();
+
+ /**
+ * Returns the simple name of the class represented by this {@code Class} as
+ * defined in the source code. If there is no name (that is, the class is
+ * anonymous) then an empty string is returned. If the receiver is an array
+ * then the name of the underlying type with square braces appended (for
+ * example {@code "Integer[]"}) is returned.
+ *
+ * @return the simple name of the class represented by this {@code Class}.
+ */
+ public String getSimpleName() {
+ if (isArray()) {
+ return getComponentType().getSimpleName() + "[]";
+ }
+
+ if (isAnonymousClass()) {
+ return "";
+ }
+
+ if (isMemberClass() || isLocalClass()) {
+ return getInnerClassName();
+ }
+
+ String name = getName();
+ int dot = name.lastIndexOf('.');
+ if (dot != -1) {
+ return name.substring(dot + 1);
+ }
+
+ return name;
+ }
+
+ /**
+ * Returns the simple name of a member or local class, or null otherwise.
+ */
+ private String getInnerClassName() {
+ return AnnotationAccess.getInnerClassName(this);
+ }
+
+ /**
+ * Returns null.
+ */
+ public ProtectionDomain getProtectionDomain() {
+ return null;
+ }
+
+ /**
+ * Returns the URL of the given resource, or null if the resource is not found.
+ * The mapping between the resource name and the URL is managed by the class' class loader.
+ *
+ * @see ClassLoader
+ */
+ public URL getResource(String resourceName) {
+ // Get absolute resource name, but without the leading slash
+ if (resourceName.startsWith("/")) {
+ resourceName = resourceName.substring(1);
+ } else {
+ String pkg = getName();
+ int dot = pkg.lastIndexOf('.');
+ if (dot != -1) {
+ pkg = pkg.substring(0, dot).replace('.', '/');
+ } else {
+ pkg = "";
+ }
+
+ resourceName = pkg + "/" + resourceName;
+ }
+
+ // Delegate to proper class loader
+ ClassLoader loader = getClassLoader();
+ if (loader != null) {
+ return loader.getResource(resourceName);
+ } else {
+ return ClassLoader.getSystemResource(resourceName);
+ }
+ }
+
+ /**
+ * Returns a read-only stream for the contents of the given resource, or null if the resource
+ * is not found.
+ * The mapping between the resource name and the stream is managed by the class' class loader.
+ *
+ * @see ClassLoader
+ */
+ public InputStream getResourceAsStream(String resourceName) {
+ // Get absolute resource name, but without the leading slash
+ if (resourceName.startsWith("/")) {
+ resourceName = resourceName.substring(1);
+ } else {
+ String pkg = getName();
+ int dot = pkg.lastIndexOf('.');
+ if (dot != -1) {
+ pkg = pkg.substring(0, dot).replace('.', '/');
+ } else {
+ pkg = "";
+ }
+
+ resourceName = pkg + "/" + resourceName;
+ }
+
+ // Delegate to proper class loader
+ ClassLoader loader = getClassLoader();
+ if (loader != null) {
+ return loader.getResourceAsStream(resourceName);
+ } else {
+ return ClassLoader.getSystemResourceAsStream(resourceName);
+ }
+ }
+
+ /**
+ * Returns null. (On Android, a {@code ClassLoader} can load classes from multiple dex files.
+ * All classes from any given dex file will have the same signers, but different dex
+ * files may have different signers. This does not fit well with the original
+ * {@code ClassLoader}-based model of {@code getSigners}.)
+ */
+ public Object[] getSigners() {
+ // See http://code.google.com/p/android/issues/detail?id=1766.
+ return null;
+ }
+
+ /**
+ * Returns the {@code Class} object which represents the superclass of the
+ * class represented by this {@code Class}. If this {@code Class} represents
+ * the {@code Object} class, a primitive type, an interface or void then the
+ * method returns {@code null}. If this {@code Class} represents an array
+ * class then the {@code Object} class is returned.
+ */
+ public Class<? super T> getSuperclass() {
+ // For interfaces superClass is Object (which agrees with the JNI spec)
+ // but not with the expected behavior here.
+ if (isInterface()) {
+ return null;
+ } else {
+ return superClass;
+ }
+ }
+
+ /**
+ * Returns an array containing {@code TypeVariable} objects for type
+ * variables declared by the generic class represented by this {@code
+ * Class}. Returns an empty array if the class is not generic.
+ */
+ @SuppressWarnings("unchecked")
+ @Override public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
+ String annotationSignature = AnnotationAccess.getSignature(this);
+ if (annotationSignature == null) {
+ return EmptyArray.TYPE_VARIABLE;
+ }
+ GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
+ parser.parseForClass(this, annotationSignature);
+ return parser.formalTypeParameters;
+ }
+
+ /**
+ * Tests whether this {@code Class} represents an annotation class.
+ */
+ public boolean isAnnotation() {
+ final int ACC_ANNOTATION = 0x2000; // not public in reflect.Modifier
+ return (accessFlags & ACC_ANNOTATION) != 0;
+ }
+
+ @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ return AnnotationAccess.isAnnotationPresent(this, annotationType);
+ }
+
+ /**
+ * Tests whether the class represented by this {@code Class} is
+ * anonymous.
+ */
+ public boolean isAnonymousClass() {
+ return AnnotationAccess.isAnonymousClass(this);
+ }
+
+ /**
+ * Tests whether the class represented by this {@code Class} is an array class.
+ */
+ public boolean isArray() {
+ return getComponentType() != null;
+ }
+
+ /**
+ * Is this a runtime created proxy class?
+ *
+ * @hide
+ */
+ public boolean isProxy() {
+ return (accessFlags & 0x00040000) != 0;
+ }
+
+ /**
+ * Can {@code c} be assigned to this class? For example, String can be assigned to Object
+ * (by an upcast), however, an Object cannot be assigned to a String as a potentially exception
+ * throwing downcast would be necessary. Similarly for interfaces, a class that implements (or
+ * an interface that extends) another can be assigned to its parent, but not vice-versa. All
+ * Classes may assign to themselves. Classes for primitive types may not assign to each other.
+ *
+ * @param c the class to check.
+ * @return {@code true} if {@code c} can be assigned to the class
+ * represented by this {@code Class}; {@code false} otherwise.
+ * @throws NullPointerException if {@code c} is {@code null}.
+ */
+ public boolean isAssignableFrom(Class<?> c) {
+ if (this == c) {
+ return true; // Can always assign to things of the same type.
+ } else if (this == Object.class) {
+ return !c.isPrimitive(); // Can assign any reference to java.lang.Object.
+ } else if (isArray()) {
+ return c.isArray() && componentType.isAssignableFrom(c.componentType);
+ } else if (isInterface()) {
+ // Search iftable which has a flattened and uniqued list of interfaces.
+ Object[] iftable = c.ifTable;
+ if (iftable != null) {
+ for (int i = 0; i < iftable.length; i += 2) {
+ Class<?> ifc = (Class<?>) iftable[i];
+ if (ifc == this) {
+ return true;
+ }
+ }
+ }
+ return false;
+ } else {
+ if (!c.isInterface()) {
+ for (c = c.superClass; c != null; c = c.superClass) {
+ if (c == this) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Tests whether the class represented by this {@code Class} is an
+ * {@code enum}.
+ */
+ public boolean isEnum() {
+ return (getSuperclass() == Enum.class) && ((accessFlags & 0x4000) != 0);
+ }
+
+ /**
+ * Tests whether the given object can be cast to the class
+ * represented by this {@code Class}. This is the runtime version of the
+ * {@code instanceof} operator.
+ *
+ * @return {@code true} if {@code object} can be cast to the type
+ * represented by this {@code Class}; {@code false} if {@code
+ * object} is {@code null} or cannot be cast.
+ */
+ public boolean isInstance(Object object) {
+ if (object == null) {
+ return false;
+ }
+ return isAssignableFrom(object.getClass());
+ }
+
+ /**
+ * Tests whether this {@code Class} represents an interface.
+ */
+ public boolean isInterface() {
+ return (accessFlags & Modifier.INTERFACE) != 0;
+ }
+
+ /**
+ * Tests whether the class represented by this {@code Class} is defined
+ * locally.
+ */
+ public boolean isLocalClass() {
+ return !classNameImpliesTopLevel()
+ && AnnotationAccess.getEnclosingMethodOrConstructor(this) != null
+ && !isAnonymousClass();
+ }
+
+ /**
+ * Tests whether the class represented by this {@code Class} is a member
+ * class.
+ */
+ public boolean isMemberClass() {
+ return getDeclaringClass() != null;
+ }
+
+ /**
+ * Tests whether this {@code Class} represents a primitive type.
+ */
+ public boolean isPrimitive() {
+ return primitiveType != 0;
+ }
+
+ /**
+ * Tests whether this {@code Class} represents a synthetic type.
+ */
+ public boolean isSynthetic() {
+ final int ACC_SYNTHETIC = 0x1000; // not public in reflect.Modifier
+ return (accessFlags & ACC_SYNTHETIC) != 0;
+ }
+
+ /**
+ * Indicates whether this {@code Class} or its parents override finalize.
+ *
+ * @hide
+ */
+ public boolean isFinalizable() {
+ final int ACC_CLASS_IS_FINALIZABLE = 0x80000000; // not public in reflect.Modifier
+ return (accessFlags & ACC_CLASS_IS_FINALIZABLE) != 0;
+ }
+
+ /**
+ * Returns a new instance of the class represented by this {@code Class},
+ * created by invoking the default (that is, zero-argument) constructor. If
+ * there is no such constructor, or if the creation fails (either because of
+ * a lack of available memory or because an exception is thrown by the
+ * constructor), an {@code InstantiationException} is thrown. If the default
+ * constructor exists but is not accessible from the context where this
+ * method is invoked, an {@code IllegalAccessException} is thrown.
+ *
+ * @throws IllegalAccessException
+ * if the default constructor is not visible.
+ * @throws InstantiationException
+ * if the instance cannot be created.
+ */
+ public T newInstance() throws InstantiationException, IllegalAccessException {
+ if (isPrimitive() || isInterface() || isArray() || Modifier.isAbstract(accessFlags)) {
+ throw new InstantiationException(this + " cannot be instantiated");
+ }
+ Class<?> caller = VMStack.getStackClass1();
+ if (!caller.canAccess(this)) {
+ throw new IllegalAccessException(this + " is not accessible from " + caller);
+ }
+ Constructor<T> init;
+ try {
+ init = getDeclaredConstructor();
+ } catch (NoSuchMethodException e) {
+ InstantiationException t =
+ new InstantiationException(this + " has no zero argument constructor");
+ t.initCause(e);
+ throw t;
+ }
+ if (!caller.canAccessMember(this, init.getAccessFlags())) {
+ throw new IllegalAccessException(init + " is not accessible from " + caller);
+ }
+ try {
+ return init.newInstance();
+ } catch (InvocationTargetException e) {
+ InstantiationException t = new InstantiationException(this);
+ t.initCause(e);
+ throw t;
+ }
+ }
+
+ private boolean canAccess(Class<?> c) {
+ if(Modifier.isPublic(c.accessFlags)) {
+ return true;
+ }
+ return inSamePackage(c);
+ }
+
+ private boolean canAccessMember(Class<?> memberClass, int memberModifiers) {
+ if (memberClass == this || Modifier.isPublic(memberModifiers)) {
+ return true;
+ }
+ if (Modifier.isPrivate(memberModifiers)) {
+ return false;
+ }
+ if (Modifier.isProtected(memberModifiers)) {
+ for (Class<?> parent = this.superClass; parent != null; parent = parent.superClass) {
+ if (parent == memberClass) {
+ return true;
+ }
+ }
+ }
+ return inSamePackage(memberClass);
+ }
+
+ private boolean inSamePackage(Class<?> c) {
+ if (classLoader != c.classLoader) {
+ return false;
+ }
+ String packageName1 = getPackageName$();
+ String packageName2 = c.getPackageName$();
+ if (packageName1 == null) {
+ return packageName2 == null;
+ } else if (packageName2 == null) {
+ return false;
+ } else {
+ return packageName1.equals(packageName2);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (isPrimitive()) {
+ return getSimpleName();
+ } else {
+ return (isInterface() ? "interface " : "class ") + getName();
+ }
+ }
+
+ /**
+ * Returns the {@code Package} of which the class represented by this
+ * {@code Class} is a member. Returns {@code null} if no {@code Package}
+ * object was created by the class loader of the class.
+ */
+ public Package getPackage() {
+ // TODO This might be a hack, but the VM doesn't have the necessary info.
+ ClassLoader loader = getClassLoader();
+ if (loader != null) {
+ String packageName = getPackageName$();
+ return packageName != null ? loader.getPackage(packageName) : null;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the package name of this class. This returns null for classes in
+ * the default package.
+ *
+ * @hide
+ */
+ public String getPackageName$() {
+ String name = getName();
+ int last = name.lastIndexOf('.');
+ return last == -1 ? null : name.substring(0, last);
+ }
+
+ /**
+ * Returns the assertion status for the class represented by this {@code
+ * Class}. Assertion is enabled / disabled based on the class loader,
+ * package or class default at runtime.
+ */
+ public boolean desiredAssertionStatus() {
+ return false;
+ }
+
+ /**
+ * Casts this {@code Class} to represent a subclass of the given class.
+ * If successful, this {@code Class} is returned; otherwise a {@code
+ * ClassCastException} is thrown.
+ *
+ * @throws ClassCastException
+ * if this {@code Class} cannot be cast to the given type.
+ */
+ @SuppressWarnings("unchecked")
+ public <U> Class<? extends U> asSubclass(Class<U> c) {
+ if (c.isAssignableFrom(this)) {
+ return (Class<? extends U>)this;
+ }
+ String actualClassName = this.getName();
+ String desiredClassName = c.getName();
+ throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
+ }
+
+ /**
+ * Casts the given object to the type represented by this {@code Class}.
+ * If the object is {@code null} then the result is also {@code null}.
+ *
+ * @throws ClassCastException
+ * if the object cannot be cast to the given type.
+ */
+ @SuppressWarnings("unchecked")
+ public T cast(Object obj) {
+ if (obj == null) {
+ return null;
+ } else if (this.isInstance(obj)) {
+ return (T)obj;
+ }
+ String actualClassName = obj.getClass().getName();
+ String desiredClassName = this.getName();
+ throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
+ }
+
+ /**
+ * The class def of this class in its own Dex, or -1 if there is no class def.
+ *
+ * @hide
+ */
+ public int getDexClassDefIndex() {
+ return (dexClassDefIndex == 65535) ? -1 : dexClassDefIndex;
+ }
+
+ /**
+ * The type index of this class in its own Dex, or -1 if it is unknown. If a class is referenced
+ * by multiple Dex files, it will have a different type index in each. Dex files support 65534
+ * type indices, with 65535 representing no index.
+ *
+ * @hide
+ */
+ public int getDexTypeIndex() {
+ int typeIndex = dexTypeIndex;
+ if (typeIndex != 65535) {
+ return typeIndex;
+ }
+ synchronized (this) {
+ typeIndex = dexTypeIndex;
+ if (typeIndex == 65535) {
+ if (dexClassDefIndex >= 0) {
+ typeIndex = getDex().typeIndexFromClassDefIndex(dexClassDefIndex);
+ } else {
+ typeIndex = getDex().findTypeIndex(InternalNames.getInternalName(this));
+ if (typeIndex < 0) {
+ typeIndex = -1;
+ }
+ }
+ dexTypeIndex = typeIndex;
+ }
+ }
+ return typeIndex;
+ }
+
+ /**
+ * The annotation directory offset of this class in its own Dex, or 0 if it
+ * is unknown.
+ *
+ * TODO: 0 is a sentinel that means 'no annotations directory'; this should be -1 if unknown
+ *
+ * @hide
+ */
+ public int getDexAnnotationDirectoryOffset() {
+ Dex dex = getDex();
+ if (dex == null) {
+ return 0;
+ }
+ int classDefIndex = getDexClassDefIndex();
+ if (classDefIndex < 0) {
+ return 0;
+ }
+ return dex.annotationDirectoryOffsetFromClassDefIndex(classDefIndex);
+ }
+
+ private static class Caches {
+ /**
+ * Cache to avoid frequent recalculation of generic interfaces, which is generally uncommon.
+ * Sized sufficient to allow ConcurrentHashMapTest to run without recalculating its generic
+ * interfaces (required to avoid time outs). Validated by running reflection heavy code
+ * such as applications using Guice-like frameworks.
+ */
+ private static final BasicLruCache<Class, Type[]> genericInterfaces
+ = new BasicLruCache<Class, Type[]>(8);
+ }
+}
diff --git a/libart/src/main/java/java/lang/ClassLoader.java b/libart/src/main/java/java/lang/ClassLoader.java
new file mode 100644
index 0000000..fb2eb8f
--- /dev/null
+++ b/libart/src/main/java/java/lang/ClassLoader.java
@@ -0,0 +1,856 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang;
+
+import dalvik.system.PathClassLoader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.security.ProtectionDomain;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Loads classes and resources from a repository. One or more class loaders are
+ * installed at runtime. These are consulted whenever the runtime system needs a
+ * specific class that is not yet available in-memory. Typically, class loaders
+ * are grouped into a tree where child class loaders delegate all requests to
+ * parent class loaders. Only if the parent class loader cannot satisfy the
+ * request, the child class loader itself tries to handle it.
+ * <p>
+ * {@code ClassLoader} is an abstract class that implements the common
+ * infrastructure required by all class loaders. Android provides several
+ * concrete implementations of the class, with
+ * {@link dalvik.system.PathClassLoader} being the one typically used. Other
+ * applications may implement subclasses of {@code ClassLoader} to provide
+ * special ways for loading classes.
+ * </p>
+ * @see Class
+ */
+public abstract class ClassLoader {
+
+ /**
+ * The 'System' ClassLoader - the one that is responsible for loading
+ * classes from the classpath. It is not equal to the bootstrap class loader -
+ * that one handles the built-in classes.
+ *
+ * Because of a potential class initialization race between ClassLoader and
+ * java.lang.System, reproducible when using JDWP with "suspend=y", we defer
+ * creation of the system class loader until first use. We use a static
+ * inner class to get synchronization at init time without having to sync on
+ * every access.
+ *
+ * @see #getSystemClassLoader()
+ */
+ static private class SystemClassLoader {
+ public static ClassLoader loader = ClassLoader.createSystemClassLoader();
+ }
+
+ /**
+ * The parent ClassLoader.
+ */
+ private ClassLoader parent;
+
+ /**
+ * The packages known to the class loader.
+ */
+ private Map<String, Package> packages = new HashMap<String, Package>();
+
+ /**
+ * To avoid unloading individual classes, {@link java.lang.reflect.Proxy}
+ * only generates one class for each set of interfaces. This maps sets of
+ * interfaces to the proxy class that implements all of them. It is declared
+ * here so that these generated classes can be unloaded with their class
+ * loader.
+ *
+ * @hide
+ */
+ public final Map<Set<Class<?>>, Class<?>> proxyCache
+ = Collections.synchronizedMap(new HashMap<Set<Class<?>>, Class<?>>());
+
+ /**
+ * Create the system class loader. Note this is NOT the bootstrap class
+ * loader (which is managed by the VM). We use a null value for the parent
+ * to indicate that the bootstrap loader is our parent.
+ */
+ private static ClassLoader createSystemClassLoader() {
+ String classPath = System.getProperty("java.class.path", ".");
+
+ // String[] paths = classPath.split(":");
+ // URL[] urls = new URL[paths.length];
+ // for (int i = 0; i < paths.length; i++) {
+ // try {
+ // urls[i] = new URL("file://" + paths[i]);
+ // }
+ // catch (Exception ex) {
+ // ex.printStackTrace();
+ // }
+ // }
+ //
+ // return new java.net.URLClassLoader(urls, null);
+
+ // TODO Make this a java.net.URLClassLoader once we have those?
+ return new PathClassLoader(classPath, BootClassLoader.getInstance());
+ }
+
+ /**
+ * Returns the system class loader. This is the parent for new
+ * {@code ClassLoader} instances and is typically the class loader used to
+ * start the application.
+ */
+ public static ClassLoader getSystemClassLoader() {
+ return SystemClassLoader.loader;
+ }
+
+ /**
+ * Finds the URL of the resource with the specified name. The system class
+ * loader's resource lookup algorithm is used to find the resource.
+ *
+ * @return the {@code URL} object for the requested resource or {@code null}
+ * if the resource can not be found.
+ * @param resName
+ * the name of the resource to find.
+ * @see Class#getResource
+ */
+ public static URL getSystemResource(String resName) {
+ return SystemClassLoader.loader.getResource(resName);
+ }
+
+ /**
+ * Returns an enumeration of URLs for the resource with the specified name.
+ * The system class loader's resource lookup algorithm is used to find the
+ * resource.
+ *
+ * @return an enumeration of {@code URL} objects containing the requested
+ * resources.
+ * @param resName
+ * the name of the resource to find.
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ public static Enumeration<URL> getSystemResources(String resName) throws IOException {
+ return SystemClassLoader.loader.getResources(resName);
+ }
+
+ /**
+ * Returns a stream for the resource with the specified name. The system
+ * class loader's resource lookup algorithm is used to find the resource.
+ * Basically, the contents of the java.class.path are searched in order,
+ * looking for a path which matches the specified resource.
+ *
+ * @return a stream for the resource or {@code null}.
+ * @param resName
+ * the name of the resource to find.
+ * @see Class#getResourceAsStream
+ */
+ public static InputStream getSystemResourceAsStream(String resName) {
+ return SystemClassLoader.loader.getResourceAsStream(resName);
+ }
+
+ /**
+ * Constructs a new instance of this class with the system class loader as
+ * its parent.
+ */
+ protected ClassLoader() {
+ this(getSystemClassLoader(), false);
+ }
+
+ /**
+ * Constructs a new instance of this class with the specified class loader
+ * as its parent.
+ *
+ * @param parentLoader
+ * The {@code ClassLoader} to use as the new class loader's
+ * parent.
+ */
+ protected ClassLoader(ClassLoader parentLoader) {
+ this(parentLoader, false);
+ }
+
+ /*
+ * constructor for the BootClassLoader which needs parent to be null.
+ */
+ ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
+ if (parentLoader == null && !nullAllowed) {
+ throw new NullPointerException("parentLoader == null && !nullAllowed");
+ }
+ parent = parentLoader;
+ }
+
+ /**
+ * Constructs a new class from an array of bytes containing a class
+ * definition in class file format.
+ *
+ * @param classRep
+ * the memory image of a class file.
+ * @param offset
+ * the offset into {@code classRep}.
+ * @param length
+ * the length of the class file.
+ * @return the {@code Class} object created from the specified subset of
+ * data in {@code classRep}.
+ * @throws ClassFormatError
+ * if {@code classRep} does not contain a valid class.
+ * @throws IndexOutOfBoundsException
+ * if {@code offset < 0}, {@code length < 0} or if
+ * {@code offset + length} is greater than the length of
+ * {@code classRep}.
+ * @deprecated Use {@link #defineClass(String, byte[], int, int)}
+ */
+ @Deprecated
+ protected final Class<?> defineClass(byte[] classRep, int offset, int length)
+ throws ClassFormatError {
+ throw new UnsupportedOperationException("can't load this type of class file");
+ }
+
+ /**
+ * Constructs a new class from an array of bytes containing a class
+ * definition in class file format.
+ *
+ * @param className
+ * the expected name of the new class, may be {@code null} if not
+ * known.
+ * @param classRep
+ * the memory image of a class file.
+ * @param offset
+ * the offset into {@code classRep}.
+ * @param length
+ * the length of the class file.
+ * @return the {@code Class} object created from the specified subset of
+ * data in {@code classRep}.
+ * @throws ClassFormatError
+ * if {@code classRep} does not contain a valid class.
+ * @throws IndexOutOfBoundsException
+ * if {@code offset < 0}, {@code length < 0} or if
+ * {@code offset + length} is greater than the length of
+ * {@code classRep}.
+ */
+ protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length)
+ throws ClassFormatError {
+ throw new UnsupportedOperationException("can't load this type of class file");
+ }
+
+ /**
+ * Constructs a new class from an array of bytes containing a class
+ * definition in class file format and assigns the specified protection
+ * domain to the new class. If the provided protection domain is
+ * {@code null} then a default protection domain is assigned to the class.
+ *
+ * @param className
+ * the expected name of the new class, may be {@code null} if not
+ * known.
+ * @param classRep
+ * the memory image of a class file.
+ * @param offset
+ * the offset into {@code classRep}.
+ * @param length
+ * the length of the class file.
+ * @param protectionDomain
+ * the protection domain to assign to the loaded class, may be
+ * {@code null}.
+ * @return the {@code Class} object created from the specified subset of
+ * data in {@code classRep}.
+ * @throws ClassFormatError
+ * if {@code classRep} does not contain a valid class.
+ * @throws IndexOutOfBoundsException
+ * if {@code offset < 0}, {@code length < 0} or if
+ * {@code offset + length} is greater than the length of
+ * {@code classRep}.
+ * @throws NoClassDefFoundError
+ * if {@code className} is not equal to the name of the class
+ * contained in {@code classRep}.
+ */
+ protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length,
+ ProtectionDomain protectionDomain) throws java.lang.ClassFormatError {
+ throw new UnsupportedOperationException("can't load this type of class file");
+ }
+
+ /**
+ * Defines a new class with the specified name, byte code from the byte
+ * buffer and the optional protection domain. If the provided protection
+ * domain is {@code null} then a default protection domain is assigned to
+ * the class.
+ *
+ * @param name
+ * the expected name of the new class, may be {@code null} if not
+ * known.
+ * @param b
+ * the byte buffer containing the byte code of the new class.
+ * @param protectionDomain
+ * the protection domain to assign to the loaded class, may be
+ * {@code null}.
+ * @return the {@code Class} object created from the data in {@code b}.
+ * @throws ClassFormatError
+ * if {@code b} does not contain a valid class.
+ * @throws NoClassDefFoundError
+ * if {@code className} is not equal to the name of the class
+ * contained in {@code b}.
+ */
+ protected final Class<?> defineClass(String name, ByteBuffer b,
+ ProtectionDomain protectionDomain) throws ClassFormatError {
+
+ byte[] temp = new byte[b.remaining()];
+ b.get(temp);
+ return defineClass(name, temp, 0, temp.length, protectionDomain);
+ }
+
+ /**
+ * Overridden by subclasses, throws a {@code ClassNotFoundException} by
+ * default. This method is called by {@code loadClass} after the parent
+ * {@code ClassLoader} has failed to find a loaded class of the same name.
+ *
+ * @param className
+ * the name of the class to look for.
+ * @return the {@code Class} object that is found.
+ * @throws ClassNotFoundException
+ * if the class cannot be found.
+ */
+ protected Class<?> findClass(String className) throws ClassNotFoundException {
+ throw new ClassNotFoundException(className);
+ }
+
+ /**
+ * Returns the class with the specified name if it has already been loaded
+ * by the VM or {@code null} if it has not yet been loaded.
+ *
+ * @param className
+ * the name of the class to look for.
+ * @return the {@code Class} object or {@code null} if the requested class
+ * has not been loaded.
+ */
+ protected final Class<?> findLoadedClass(String className) {
+ ClassLoader loader;
+ if (this == BootClassLoader.getInstance())
+ loader = null;
+ else
+ loader = this;
+ return VMClassLoader.findLoadedClass(loader, className);
+ }
+
+ /**
+ * Finds the class with the specified name, loading it using the system
+ * class loader if necessary.
+ *
+ * @param className
+ * the name of the class to look for.
+ * @return the {@code Class} object with the requested {@code className}.
+ * @throws ClassNotFoundException
+ * if the class can not be found.
+ */
+ protected final Class<?> findSystemClass(String className) throws ClassNotFoundException {
+ return Class.forName(className, false, getSystemClassLoader());
+ }
+
+ /**
+ * Returns this class loader's parent.
+ *
+ * @return this class loader's parent or {@code null}.
+ */
+ public final ClassLoader getParent() {
+ return parent;
+ }
+
+ /**
+ * Returns the URL of the resource with the specified name. This
+ * implementation first tries to use the parent class loader to find the
+ * resource; if this fails then {@link #findResource(String)} is called to
+ * find the requested resource.
+ *
+ * @param resName
+ * the name of the resource to find.
+ * @return the {@code URL} object for the requested resource or {@code null}
+ * if the resource can not be found
+ * @see Class#getResource
+ */
+ public URL getResource(String resName) {
+ URL resource = parent.getResource(resName);
+ if (resource == null) {
+ resource = findResource(resName);
+ }
+ return resource;
+ }
+
+ /**
+ * Returns an enumeration of URLs for the resource with the specified name.
+ * This implementation first uses this class loader's parent to find the
+ * resource, then it calls {@link #findResources(String)} to get additional
+ * URLs. The returned enumeration contains the {@code URL} objects of both
+ * find operations.
+ *
+ * @return an enumeration of {@code URL} objects for the requested resource.
+ * @param resName
+ * the name of the resource to find.
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ @SuppressWarnings("unchecked")
+ public Enumeration<URL> getResources(String resName) throws IOException {
+
+ Enumeration<URL> first = parent.getResources(resName);
+ Enumeration<URL> second = findResources(resName);
+
+ return new TwoEnumerationsInOne(first, second);
+ }
+
+ /**
+ * Returns a stream for the resource with the specified name. See
+ * {@link #getResource(String)} for a description of the lookup algorithm
+ * used to find the resource.
+ *
+ * @return a stream for the resource or {@code null} if the resource can not be found
+ * @param resName
+ * the name of the resource to find.
+ * @see Class#getResourceAsStream
+ */
+ public InputStream getResourceAsStream(String resName) {
+ try {
+ URL url = getResource(resName);
+ if (url != null) {
+ return url.openStream();
+ }
+ } catch (IOException ex) {
+ // Don't want to see the exception.
+ }
+
+ return null;
+ }
+
+ /**
+ * Loads the class with the specified name. Invoking this method is
+ * equivalent to calling {@code loadClass(className, false)}.
+ * <p>
+ * <strong>Note:</strong> In the Android reference implementation, the
+ * second parameter of {@link #loadClass(String, boolean)} is ignored
+ * anyway.
+ * </p>
+ *
+ * @return the {@code Class} object.
+ * @param className
+ * the name of the class to look for.
+ * @throws ClassNotFoundException
+ * if the class can not be found.
+ */
+ public Class<?> loadClass(String className) throws ClassNotFoundException {
+ return loadClass(className, false);
+ }
+
+ /**
+ * Loads the class with the specified name, optionally linking it after
+ * loading. The following steps are performed:
+ * <ol>
+ * <li> Call {@link #findLoadedClass(String)} to determine if the requested
+ * class has already been loaded.</li>
+ * <li>If the class has not yet been loaded: Invoke this method on the
+ * parent class loader.</li>
+ * <li>If the class has still not been loaded: Call
+ * {@link #findClass(String)} to find the class.</li>
+ * </ol>
+ * <p>
+ * <strong>Note:</strong> In the Android reference implementation, the
+ * {@code resolve} parameter is ignored; classes are never linked.
+ * </p>
+ *
+ * @return the {@code Class} object.
+ * @param className
+ * the name of the class to look for.
+ * @param resolve
+ * Indicates if the class should be resolved after loading. This
+ * parameter is ignored on the Android reference implementation;
+ * classes are not resolved.
+ * @throws ClassNotFoundException
+ * if the class can not be found.
+ */
+ protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
+ Class<?> clazz = findLoadedClass(className);
+
+ if (clazz == null) {
+ ClassNotFoundException suppressed = null;
+ try {
+ clazz = parent.loadClass(className, false);
+ } catch (ClassNotFoundException e) {
+ suppressed = e;
+ }
+
+ if (clazz == null) {
+ try {
+ clazz = findClass(className);
+ } catch (ClassNotFoundException e) {
+ e.addSuppressed(suppressed);
+ throw e;
+ }
+ }
+ }
+
+ return clazz;
+ }
+
+ /**
+ * Forces a class to be linked (initialized). If the class has already been
+ * linked this operation has no effect.
+ * <p>
+ * <strong>Note:</strong> In the Android reference implementation, this
+ * method has no effect.
+ * </p>
+ *
+ * @param clazz
+ * the class to link.
+ */
+ protected final void resolveClass(Class<?> clazz) {
+ // no-op, doesn't make sense on android.
+ }
+
+ /**
+ * Finds the URL of the resource with the specified name. This
+ * implementation just returns {@code null}; it should be overridden in
+ * subclasses.
+ *
+ * @param resName
+ * the name of the resource to find.
+ * @return the {@code URL} object for the requested resource.
+ */
+ protected URL findResource(String resName) {
+ return null;
+ }
+
+ /**
+ * Finds an enumeration of URLs for the resource with the specified name.
+ * This implementation just returns an empty {@code Enumeration}; it should
+ * be overridden in subclasses.
+ *
+ * @param resName
+ * the name of the resource to find.
+ * @return an enumeration of {@code URL} objects for the requested resource.
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ @SuppressWarnings( {
+ "unchecked", "unused"
+ })
+ protected Enumeration<URL> findResources(String resName) throws IOException {
+ return Collections.emptyEnumeration();
+ }
+
+ /**
+ * Returns the absolute path of the native library with the specified name,
+ * or {@code null}. If this method returns {@code null} then the virtual
+ * machine searches the directories specified by the system property
+ * "java.library.path".
+ * <p>
+ * This implementation always returns {@code null}.
+ * </p>
+ *
+ * @param libName
+ * the name of the library to find.
+ * @return the absolute path of the library.
+ */
+ protected String findLibrary(String libName) {
+ return null;
+ }
+
+ /**
+ * Returns the package with the specified name. Package information is
+ * searched in this class loader.
+ *
+ * @param name
+ * the name of the package to find.
+ * @return the package with the requested name; {@code null} if the package
+ * can not be found.
+ */
+ protected Package getPackage(String name) {
+ synchronized (packages) {
+ return packages.get(name);
+ }
+ }
+
+ /**
+ * Returns all the packages known to this class loader.
+ *
+ * @return an array with all packages known to this class loader.
+ */
+ protected Package[] getPackages() {
+ synchronized (packages) {
+ Collection<Package> col = packages.values();
+ Package[] result = new Package[col.size()];
+ col.toArray(result);
+ return result;
+ }
+ }
+
+ /**
+ * Defines and returns a new {@code Package} using the specified
+ * information. If {@code sealBase} is {@code null}, the package is left
+ * unsealed. Otherwise, the package is sealed using this URL.
+ *
+ * @param name
+ * the name of the package.
+ * @param specTitle
+ * the title of the specification.
+ * @param specVersion
+ * the version of the specification.
+ * @param specVendor
+ * the vendor of the specification.
+ * @param implTitle
+ * the implementation title.
+ * @param implVersion
+ * the implementation version.
+ * @param implVendor
+ * the specification vendor.
+ * @param sealBase
+ * the URL used to seal this package or {@code null} to leave the
+ * package unsealed.
+ * @return the {@code Package} object that has been created.
+ * @throws IllegalArgumentException
+ * if a package with the specified name already exists.
+ */
+ protected Package definePackage(String name, String specTitle, String specVersion,
+ String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
+ throws IllegalArgumentException {
+
+ synchronized (packages) {
+ if (packages.containsKey(name)) {
+ throw new IllegalArgumentException("Package " + name + " already defined");
+ }
+
+ Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle,
+ implVersion, implVendor, sealBase);
+
+ packages.put(name, newPackage);
+
+ return newPackage;
+ }
+ }
+
+ /**
+ * Sets the signers of the specified class. This implementation does
+ * nothing.
+ *
+ * @param c
+ * the {@code Class} object for which to set the signers.
+ * @param signers
+ * the signers for {@code c}.
+ */
+ protected final void setSigners(Class<?> c, Object[] signers) {
+ }
+
+ /**
+ * Sets the assertion status of the class with the specified name.
+ * <p>
+ * <strong>Note: </strong>This method does nothing in the Android reference
+ * implementation.
+ * </p>
+ *
+ * @param cname
+ * the name of the class for which to set the assertion status.
+ * @param enable
+ * the new assertion status.
+ */
+ public void setClassAssertionStatus(String cname, boolean enable) {
+ }
+
+ /**
+ * Sets the assertion status of the package with the specified name.
+ * <p>
+ * <strong>Note: </strong>This method does nothing in the Android reference
+ * implementation.
+ * </p>
+ *
+ * @param pname
+ * the name of the package for which to set the assertion status.
+ * @param enable
+ * the new assertion status.
+ */
+ public void setPackageAssertionStatus(String pname, boolean enable) {
+ }
+
+ /**
+ * Sets the default assertion status for this class loader.
+ * <p>
+ * <strong>Note: </strong>This method does nothing in the Android reference
+ * implementation.
+ * </p>
+ *
+ * @param enable
+ * the new assertion status.
+ */
+ public void setDefaultAssertionStatus(boolean enable) {
+ }
+
+ /**
+ * Sets the default assertion status for this class loader to {@code false}
+ * and removes any package default and class assertion status settings.
+ * <p>
+ * <strong>Note:</strong> This method does nothing in the Android reference
+ * implementation.
+ * </p>
+ */
+ public void clearAssertionStatus() {
+ }
+}
+
+/*
+ * Provides a helper class that combines two existing URL enumerations into one.
+ * It is required for the getResources() methods. Items are fetched from the
+ * first enumeration until it's empty, then from the second one.
+ */
+class TwoEnumerationsInOne implements Enumeration<URL> {
+
+ private final Enumeration<URL> first;
+
+ private final Enumeration<URL> second;
+
+ public TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return first.hasMoreElements() || second.hasMoreElements();
+ }
+
+ @Override
+ public URL nextElement() {
+ if (first.hasMoreElements()) {
+ return first.nextElement();
+ } else {
+ return second.nextElement();
+ }
+ }
+
+}
+
+/**
+ * Provides an explicit representation of the boot class loader. It sits at the
+ * head of the class loader chain and delegates requests to the VM's internal
+ * class loading mechanism.
+ */
+class BootClassLoader extends ClassLoader {
+
+ private static BootClassLoader instance;
+
+ @FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
+ public static synchronized BootClassLoader getInstance() {
+ if (instance == null) {
+ instance = new BootClassLoader();
+ }
+
+ return instance;
+ }
+
+ public BootClassLoader() {
+ super(null, true);
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ return Class.classForName(name, false, null);
+ }
+
+ @Override
+ protected URL findResource(String name) {
+ return VMClassLoader.getResource(name);
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ protected Enumeration<URL> findResources(String resName) throws IOException {
+ return Collections.enumeration(VMClassLoader.getResources(resName));
+ }
+
+ /**
+ * Returns package information for the given package. Unfortunately, the
+ * Android BootClassLoader doesn't really have this information, and as a
+ * non-secure ClassLoader, it isn't even required to, according to the spec.
+ * Yet, we want to provide it, in order to make all those hopeful callers of
+ * {@code myClass.getPackage().getName()} happy. Thus we construct a Package
+ * object the first time it is being requested and fill most of the fields
+ * with dummy values. The Package object is then put into the ClassLoader's
+ * Package cache, so we see the same one next time. We don't create Package
+ * objects for null arguments or for the default package.
+ * <p>
+ * There a limited chance that we end up with multiple Package objects
+ * representing the same package: It can happen when when a package is
+ * scattered across different JAR files being loaded by different
+ * ClassLoaders. Rather unlikely, and given that this whole thing is more or
+ * less a workaround, probably not worth the effort.
+ */
+ @Override
+ protected Package getPackage(String name) {
+ if (name != null && !name.isEmpty()) {
+ synchronized (this) {
+ Package pack = super.getPackage(name);
+
+ if (pack == null) {
+ pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0",
+ "Unknown", null);
+ }
+
+ return pack;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public URL getResource(String resName) {
+ return findResource(resName);
+ }
+
+ @Override
+ protected Class<?> loadClass(String className, boolean resolve)
+ throws ClassNotFoundException {
+ Class<?> clazz = findLoadedClass(className);
+
+ if (clazz == null) {
+ clazz = findClass(className);
+ }
+
+ return clazz;
+ }
+
+ @Override
+ public Enumeration<URL> getResources(String resName) throws IOException {
+ return findResources(resName);
+ }
+}
+
+/**
+ * TODO Open issues - Missing / empty methods - Signer stuff - Protection
+ * domains - Assertions
+ */
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java
new file mode 100644
index 0000000..1422c13
--- /dev/null
+++ b/libart/src/main/java/java/lang/Daemons.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2011 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 java.lang;
+
+import dalvik.system.VMRuntime;
+import java.lang.ref.FinalizerReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.util.concurrent.TimeoutException;
+import libcore.util.EmptyArray;
+
+/**
+ * Calls Object.finalize() on objects in the finalizer reference queue. The VM
+ * will abort if any finalize() call takes more than the maximum finalize time
+ * to complete.
+ *
+ * @hide
+ */
+public final class Daemons {
+ private static final int NANOS_PER_MILLI = 1000 * 1000;
+ private static final int NANOS_PER_SECOND = NANOS_PER_MILLI * 1000;
+ private static final long MAX_FINALIZE_NANOS = 10L * NANOS_PER_SECOND;
+
+ public static void start() {
+ ReferenceQueueDaemon.INSTANCE.start();
+ FinalizerDaemon.INSTANCE.start();
+ FinalizerWatchdogDaemon.INSTANCE.start();
+ HeapTrimmerDaemon.INSTANCE.start();
+ GCDaemon.INSTANCE.start();
+ }
+
+ public static void stop() {
+ ReferenceQueueDaemon.INSTANCE.stop();
+ FinalizerDaemon.INSTANCE.stop();
+ FinalizerWatchdogDaemon.INSTANCE.stop();
+ HeapTrimmerDaemon.INSTANCE.stop();
+ GCDaemon.INSTANCE.stop();
+ }
+
+ /**
+ * A background task that provides runtime support to the application.
+ * Daemons can be stopped and started, but only so that the zygote can be a
+ * single-threaded process when it forks.
+ */
+ private static abstract class Daemon implements Runnable {
+ private Thread thread;
+
+ public synchronized void start() {
+ if (thread != null) {
+ throw new IllegalStateException("already running");
+ }
+ thread = new Thread(ThreadGroup.systemThreadGroup, this, getClass().getSimpleName());
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ public abstract void run();
+
+ /**
+ * Returns true while the current thread should continue to run; false
+ * when it should return.
+ */
+ protected synchronized boolean isRunning() {
+ return thread != null;
+ }
+
+ public synchronized void interrupt() {
+ if (thread == null) {
+ throw new IllegalStateException("not running");
+ }
+ thread.interrupt();
+ }
+
+ /**
+ * Waits for the runtime thread to stop. This interrupts the thread
+ * currently running the runnable and then waits for it to exit.
+ */
+ public void stop() {
+ Thread threadToStop;
+ synchronized (this) {
+ threadToStop = thread;
+ thread = null;
+ }
+ if (threadToStop == null) {
+ throw new IllegalStateException("not running");
+ }
+ threadToStop.interrupt();
+ while (true) {
+ try {
+ threadToStop.join();
+ return;
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+
+ /**
+ * Returns the current stack trace of the thread, or an empty stack trace
+ * if the thread is not currently running.
+ */
+ public synchronized StackTraceElement[] getStackTrace() {
+ return thread != null ? thread.getStackTrace() : EmptyArray.STACK_TRACE_ELEMENT;
+ }
+ }
+
+ /**
+ * This heap management thread moves elements from the garbage collector's
+ * pending list to the managed reference queue.
+ */
+ private static class ReferenceQueueDaemon extends Daemon {
+ private static final ReferenceQueueDaemon INSTANCE = new ReferenceQueueDaemon();
+
+ @Override public void run() {
+ while (isRunning()) {
+ Reference<?> list;
+ try {
+ synchronized (ReferenceQueue.class) {
+ while (ReferenceQueue.unenqueued == null) {
+ ReferenceQueue.class.wait();
+ }
+ list = ReferenceQueue.unenqueued;
+ ReferenceQueue.unenqueued = null;
+ }
+ } catch (InterruptedException e) {
+ continue;
+ }
+ enqueue(list);
+ }
+ }
+
+ private void enqueue(Reference<?> list) {
+ while (list != null) {
+ Reference<?> reference;
+ // pendingNext is owned by the GC so no synchronization is required
+ if (list == list.pendingNext) {
+ reference = list;
+ reference.pendingNext = null;
+ list = null;
+ } else {
+ reference = list.pendingNext;
+ list.pendingNext = reference.pendingNext;
+ reference.pendingNext = null;
+ }
+ reference.enqueueInternal();
+ }
+ }
+ }
+
+ private static class FinalizerDaemon extends Daemon {
+ private static final FinalizerDaemon INSTANCE = new FinalizerDaemon();
+ private final ReferenceQueue<Object> queue = FinalizerReference.queue;
+ private volatile Object finalizingObject;
+ private volatile long finalizingStartedNanos;
+
+ @Override public void run() {
+ while (isRunning()) {
+ // Take a reference, blocking until one is ready or the thread should stop
+ try {
+ doFinalize((FinalizerReference<?>) queue.remove());
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+
+ @FindBugsSuppressWarnings("FI_EXPLICIT_INVOCATION")
+ private void doFinalize(FinalizerReference<?> reference) {
+ FinalizerReference.remove(reference);
+ Object object = reference.get();
+ reference.clear();
+ try {
+ finalizingStartedNanos = System.nanoTime();
+ finalizingObject = object;
+ synchronized (FinalizerWatchdogDaemon.INSTANCE) {
+ FinalizerWatchdogDaemon.INSTANCE.notify();
+ }
+ object.finalize();
+ } catch (Throwable ex) {
+ // The RI silently swallows these, but Android has always logged.
+ System.logE("Uncaught exception thrown by finalizer", ex);
+ } finally {
+ finalizingObject = null;
+ }
+ }
+ }
+
+ /**
+ * The watchdog exits the VM if the finalizer ever gets stuck. We consider
+ * the finalizer to be stuck if it spends more than MAX_FINALIZATION_MILLIS
+ * on one instance.
+ */
+ private static class FinalizerWatchdogDaemon extends Daemon {
+ private static final FinalizerWatchdogDaemon INSTANCE = new FinalizerWatchdogDaemon();
+
+ @Override public void run() {
+ while (isRunning()) {
+ Object object = waitForObject();
+ if (object == null) {
+ // We have been interrupted, need to see if this daemon has been stopped.
+ continue;
+ }
+ boolean finalized = waitForFinalization(object);
+ if (!finalized && !VMRuntime.getRuntime().isDebuggerActive()) {
+ finalizerTimedOut(object);
+ break;
+ }
+ }
+ }
+
+ private Object waitForObject() {
+ while (true) {
+ Object object = FinalizerDaemon.INSTANCE.finalizingObject;
+ if (object != null) {
+ return object;
+ }
+ synchronized (this) {
+ // wait until something is ready to be finalized
+ // http://code.google.com/p/android/issues/detail?id=22778
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ // Daemon.stop may have interrupted us.
+ return null;
+ }
+ }
+ }
+ }
+
+ private void sleepFor(long startNanos, long durationNanos) {
+ while (true) {
+ long elapsedNanos = System.nanoTime() - startNanos;
+ long sleepNanos = durationNanos - elapsedNanos;
+ long sleepMills = sleepNanos / NANOS_PER_MILLI;
+ if (sleepMills <= 0) {
+ return;
+ }
+ try {
+ Thread.sleep(sleepMills);
+ } catch (InterruptedException e) {
+ if (!isRunning()) {
+ return;
+ }
+ }
+ }
+ }
+
+ private boolean waitForFinalization(Object object) {
+ sleepFor(FinalizerDaemon.INSTANCE.finalizingStartedNanos, MAX_FINALIZE_NANOS);
+ return object != FinalizerDaemon.INSTANCE.finalizingObject;
+ }
+
+ private static void finalizerTimedOut(Object object) {
+ // The current object has exceeded the finalization deadline; abort!
+ String message = object.getClass().getName() + ".finalize() timed out after "
+ + (MAX_FINALIZE_NANOS / NANOS_PER_SECOND) + " seconds";
+ Exception syntheticException = new TimeoutException(message);
+ // We use the stack from where finalize() was running to show where it was stuck.
+ syntheticException.setStackTrace(FinalizerDaemon.INSTANCE.getStackTrace());
+ Thread.UncaughtExceptionHandler h = Thread.getDefaultUncaughtExceptionHandler();
+ if (h == null) {
+ // If we have no handler, log and exit.
+ System.logE(message, syntheticException);
+ System.exit(2);
+ }
+ // Otherwise call the handler to do crash reporting.
+ // We don't just throw because we're not the thread that
+ // timed out; we're the thread that detected it.
+ h.uncaughtException(Thread.currentThread(), syntheticException);
+ }
+ }
+
+ // Invoked by the GC to request that the HeapTrimmerDaemon thread attempt to trim the heap.
+ public static void requestHeapTrim() {
+ synchronized (HeapTrimmerDaemon.INSTANCE) {
+ HeapTrimmerDaemon.INSTANCE.notify();
+ }
+ }
+
+ private static class HeapTrimmerDaemon extends Daemon {
+ private static final HeapTrimmerDaemon INSTANCE = new HeapTrimmerDaemon();
+
+ @Override public void run() {
+ while (isRunning()) {
+ try {
+ synchronized (this) {
+ wait();
+ }
+ VMRuntime.getRuntime().trimHeap();
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+
+ // Invoked by the GC to request that the HeapTrimmerDaemon thread attempt to trim the heap.
+ public static void requestGC() {
+ GCDaemon.INSTANCE.requestGC();
+ }
+
+ private static class GCDaemon extends Daemon {
+ private static final GCDaemon INSTANCE = new GCDaemon();
+ private int count = 0;
+
+ public void requestGC() {
+ synchronized (this) {
+ ++count;
+ notify();
+ }
+ }
+
+ @Override public void run() {
+ while (isRunning()) {
+ try {
+ synchronized (this) {
+ // Wait until a request comes in, unless we have a pending request.
+ while (count == 0) {
+ wait();
+ }
+ --count;
+ }
+ VMRuntime.getRuntime().concurrentGC();
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+}
diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java
new file mode 100644
index 0000000..3603f9c
--- /dev/null
+++ b/libart/src/main/java/java/lang/DexCache.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2012 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 java.lang;
+
+import com.android.dex.Dex;
+import java.lang.reflect.ArtField;
+import java.lang.reflect.ArtMethod;
+
+/**
+ * A dex cache holds resolved copies of strings, fields, methods, and classes from the dexfile.
+ */
+final class DexCache {
+ /** Lazily initialized dex file wrapper. Volatile to avoid double-check locking issues. */
+ private volatile Dex dex;
+
+ /** Indexed by the type index array of locations of initialized static storage. */
+ Object[] initializedStaticStorage;
+
+ /** The location of the associated dex file. */
+ String location;
+
+ /**
+ * References to fields as they become resolved following interpreter semantics. May refer to
+ * fields defined in other dex files.
+ */
+ ArtField[] resolvedFields;
+
+ /**
+ * References to methods as they become resolved following interpreter semantics. May refer to
+ * methods defined in other dex files.
+ */
+ ArtMethod[] resolvedMethods;
+
+ /**
+ * References to types as they become resolved following interpreter semantics. May refer to
+ * types defined in other dex files.
+ */
+ Class[] resolvedTypes;
+
+ /**
+ * References to strings as they become resolved following interpreter semantics. All strings
+ * are interned.
+ */
+ String[] strings;
+
+ /** Holds C pointer to dexFile. */
+ private int dexFile;
+
+ // Only created by the VM.
+ private DexCache() {}
+
+ Dex getDex() {
+ Dex result = dex;
+ if (result == null) {
+ synchronized (this) {
+ result = dex;
+ if (result == null) {
+ dex = result = getDexNative();
+ }
+ }
+ }
+ return result;
+ }
+
+ private native Dex getDexNative();
+}
+
diff --git a/libart/src/main/java/java/lang/Enum.java b/libart/src/main/java/java/lang/Enum.java
new file mode 100644
index 0000000..f98554a
--- /dev/null
+++ b/libart/src/main/java/java/lang/Enum.java
@@ -0,0 +1,222 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 java.lang;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import libcore.util.BasicLruCache;
+import libcore.util.EmptyArray;
+
+/**
+ * The superclass of all enumerated types. Actual enumeration types inherit from
+ * this class, but extending this class does not make a class an enumeration
+ * type, since the compiler needs to generate special information for it.
+ */
+public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> {
+
+ private static final long serialVersionUID = -4300926546619394005L;
+
+ private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache
+ = new BasicLruCache<Class<? extends Enum>, Object[]>(64) {
+ @Override protected Object[] create(Class<? extends Enum> enumType) {
+ if (!enumType.isEnum()) {
+ return null;
+ }
+ try {
+ Method method = enumType.getDeclaredMethod("values", EmptyArray.CLASS);
+ return (Object[]) method.invoke((Object[]) null);
+ } catch (NoSuchMethodException impossible) {
+ throw new AssertionError("impossible", impossible);
+ } catch (IllegalAccessException impossible) {
+ throw new AssertionError("impossible", impossible);
+ } catch (InvocationTargetException impossible) {
+ throw new AssertionError("impossible", impossible);
+ }
+ }
+ };
+
+ private final String name;
+
+ private final int ordinal;
+
+ /**
+ * Constructor for constants of enum subtypes.
+ *
+ * @param name
+ * the enum constant's declared name.
+ * @param ordinal
+ * the enum constant's ordinal, which corresponds to its position
+ * in the enum declaration, starting at zero.
+ */
+ protected Enum(String name, int ordinal) {
+ this.name = name;
+ this.ordinal = ordinal;
+ }
+
+ /**
+ * Returns the name of this enum constant. The name is the field as it
+ * appears in the {@code enum} declaration.
+ *
+ * @return the name of this enum constant.
+ * @see #toString()
+ */
+ public final String name() {
+ return name;
+ }
+
+ /**
+ * Returns the position of the enum constant in the declaration. The first
+ * constant has an ordinal value of zero.
+ *
+ * @return the ordinal value of this enum constant.
+ */
+ public final int ordinal() {
+ return ordinal;
+ }
+
+ /**
+ * Returns a string containing a concise, human-readable description of this
+ * object. In this case, the enum constant's name is returned.
+ *
+ * @return a printable representation of this object.
+ */
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * Compares this object with the specified object and indicates if they are
+ * equal. In order to be equal, {@code object} must be identical to this
+ * enum constant.
+ *
+ * @param other
+ * the object to compare this enum constant with.
+ * @return {@code true} if the specified object is equal to this
+ * {@code Enum}; {@code false} otherwise.
+ */
+ @Override
+ public final boolean equals(Object other) {
+ return this == other;
+ }
+
+ @Override
+ public final int hashCode() {
+ return ordinal + (name == null ? 0 : name.hashCode());
+ }
+
+ /**
+ * {@code Enum} objects are singletons, they may not be cloned. This method
+ * always throws a {@code CloneNotSupportedException}.
+ *
+ * @return does not return.
+ * @throws CloneNotSupportedException
+ * is always thrown.
+ */
+ @Override
+ protected final Object clone() throws CloneNotSupportedException {
+ throw new CloneNotSupportedException("Enums may not be cloned");
+ }
+
+ /**
+ * Compares this object to the specified enum object to determine their
+ * relative order. This method compares the object's ordinal values, that
+ * is, their position in the enum declaration.
+ *
+ * @param o
+ * the enum object to compare this object to.
+ * @return a negative value if the ordinal value of this enum constant is
+ * less than the ordinal value of {@code o}; 0 if the ordinal
+ * values of this enum constant and {@code o} are equal; a positive
+ * value if the ordinal value of this enum constant is greater than
+ * the ordinal value of {@code o}.
+ * @see java.lang.Comparable
+ */
+ public final int compareTo(E o) {
+ return ordinal - o.ordinal;
+ }
+
+ /**
+ * Returns the enum constant's declaring class.
+ *
+ * @return the class object representing the constant's enum type.
+ */
+ @SuppressWarnings("unchecked")
+ public final Class<E> getDeclaringClass() {
+ Class<?> myClass = getClass();
+ Class<?> mySuperClass = myClass.getSuperclass();
+ if (Enum.class == mySuperClass) {
+ return (Class<E>)myClass;
+ }
+ return (Class<E>)mySuperClass;
+ }
+
+ /**
+ * Returns the constant with the specified name of the specified enum type.
+ *
+ * @param enumType
+ * the class of the enumerated type to search for the constant
+ * value.
+ * @param name
+ * the name of the constant value to find.
+ * @return the enum constant.
+ * @throws NullPointerException
+ * if either {@code enumType} or {@code name} are {@code null}.
+ * @throws IllegalArgumentException
+ * if {@code enumType} is not an enumerated type or does not
+ * have a constant value called {@code name}.
+ */
+ public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
+ if (enumType == null) {
+ throw new NullPointerException("enumType == null");
+ } else if (name == null) {
+ throw new NullPointerException("name == null");
+ }
+ T[] values = getSharedConstants(enumType);
+ if (values == null) {
+ throw new IllegalArgumentException(enumType + " is not an enum type");
+ }
+ for (T value : values) {
+ if (name.equals(value.name())) {
+ return value;
+ }
+ }
+ throw new IllegalArgumentException(name + " is not a constant in " + enumType.getName());
+ }
+
+ /**
+ * Returns a shared, mutable array containing the constants of this enum. It
+ * is an error to modify the returned array.
+ *
+ * @hide
+ */
+ @SuppressWarnings("unchecked") // the cache always returns the type matching enumType
+ public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) {
+ return (T[]) sharedConstantsCache.get(enumType);
+ }
+
+ /**
+ * Enum types may not have finalizers.
+ *
+ * @since 1.6
+ */
+ @Override
+ @SuppressWarnings("FinalizeDoesntCallSuperFinalize")
+ protected final void finalize() {
+ }
+}
diff --git a/libart/src/main/java/java/lang/Object.java b/libart/src/main/java/java/lang/Object.java
new file mode 100644
index 0000000..9c59870
--- /dev/null
+++ b/libart/src/main/java/java/lang/Object.java
@@ -0,0 +1,452 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang;
+
+/**
+ * The root class of the Java class hierarchy. All non-primitive types
+ * (including arrays) inherit either directly or indirectly from this class.
+ *
+ * <a name="writing_equals"><h4>Writing a correct {@code equals} method</h4></a>
+ * <p>Follow this style to write a canonical {@code equals} method:
+ * <pre>
+ * // Use @Override to avoid accidental overloading.
+ * @Override public boolean equals(Object o) {
+ * // Return true if the objects are identical.
+ * // (This is just an optimization, not required for correctness.)
+ * if (this == o) {
+ * return true;
+ * }
+ *
+ * // Return false if the other object has the wrong type.
+ * // This type may be an interface depending on the interface's specification.
+ * if (!(o instanceof MyType)) {
+ * return false;
+ * }
+ *
+ * // Cast to the appropriate type.
+ * // This will succeed because of the instanceof, and lets us access private fields.
+ * MyType lhs = (MyType) o;
+ *
+ * // Check each field. Primitive fields, reference fields, and nullable reference
+ * // fields are all treated differently.
+ * return primitiveField == lhs.primitiveField &&
+ * referenceField.equals(lhs.referenceField) &&
+ * (nullableField == null ? lhs.nullableField == null
+ * : nullableField.equals(lhs.nullableField));
+ * }
+ * </pre>
+ * <p>If you override {@code equals}, you should also override {@code hashCode}: equal
+ * instances must have equal hash codes.
+ *
+ * <p>See <i>Effective Java</i> item 8 for much more detail and clarification.
+ *
+ * <a name="writing_hashCode"><h4>Writing a correct {@code hashCode} method</h4></a>
+ * <p>Follow this style to write a canonical {@code hashCode} method:
+ * <pre>
+ * @Override public int hashCode() {
+ * // Start with a non-zero constant.
+ * int result = 17;
+ *
+ * // Include a hash for each field.
+ * result = 31 * result + (booleanField ? 1 : 0);
+ *
+ * result = 31 * result + byteField;
+ * result = 31 * result + charField;
+ * result = 31 * result + shortField;
+ * result = 31 * result + intField;
+ *
+ * result = 31 * result + (int) (longField ^ (longField >>> 32));
+ *
+ * result = 31 * result + Float.floatToIntBits(floatField);
+ *
+ * long doubleFieldBits = Double.doubleToLongBits(doubleField);
+ * result = 31 * result + (int) (doubleFieldBits ^ (doubleFieldBits >>> 32));
+ *
+ * result = 31 * result + Arrays.hashCode(arrayField);
+ *
+ * result = 31 * result + referenceField.hashCode();
+ * result = 31 * result +
+ * (nullableReferenceField == null ? 0
+ * : nullableReferenceField.hashCode());
+ *
+ * return result;
+ * }
+ * </pre>
+ *
+ * <p>If you don't intend your type to be used as a hash key, don't simply rely on the default
+ * {@code hashCode} implementation, because that silently and non-obviously breaks any future
+ * code that does use your type as a hash key. You should throw instead:
+ * <pre>
+ * @Override public int hashCode() {
+ * throw new UnsupportedOperationException();
+ * }
+ * </pre>
+ *
+ * <p>See <i>Effective Java</i> item 9 for much more detail and clarification.
+ *
+ * <a name="writing_toString"><h4>Writing a useful {@code toString} method</h4></a>
+ * <p>For debugging convenience, it's common to override {@code toString} in this style:
+ * <pre>
+ * @Override public String toString() {
+ * return getClass().getName() + "[" +
+ * "primitiveField=" + primitiveField + ", " +
+ * "referenceField=" + referenceField + ", " +
+ * "arrayField=" + Arrays.toString(arrayField) + "]";
+ * }
+ * </pre>
+ * <p>The set of fields to include is generally the same as those that would be tested
+ * in your {@code equals} implementation.
+ * <p>See <i>Effective Java</i> item 10 for much more detail and clarification.
+ */
+public class Object {
+
+ private transient Class<?> shadow$_klass_;
+ private transient int shadow$_monitor_;
+
+ /**
+ * Constructs a new instance of {@code Object}.
+ */
+ public Object() {
+ if (shadow$_klass_.isFinalizable()) {
+ java.lang.ref.FinalizerReference.add(this);
+ }
+ }
+
+ /**
+ * Creates and returns a copy of this {@code Object}. The default
+ * implementation returns a so-called "shallow" copy: It creates a new
+ * instance of the same class and then copies the field values (including
+ * object references) from this instance to the new instance. A "deep" copy,
+ * in contrast, would also recursively clone nested objects. A subclass that
+ * needs to implement this kind of cloning should call {@code super.clone()}
+ * to create the new instance and then create deep copies of the nested,
+ * mutable objects.
+ *
+ * @return a copy of this object.
+ * @throws CloneNotSupportedException
+ * if this object's class does not implement the {@code
+ * Cloneable} interface.
+ */
+ protected Object clone() throws CloneNotSupportedException {
+ if (!(this instanceof Cloneable)) {
+ throw new CloneNotSupportedException("Class " + getClass().getName() +
+ " doesn't implement Cloneable");
+ }
+
+ return internalClone();
+ }
+
+ /*
+ * Native helper method for cloning.
+ */
+ private native Object internalClone();
+
+ /**
+ * Compares this instance with the specified object and indicates if they
+ * are equal. In order to be equal, {@code o} must represent the same object
+ * as this instance using a class-specific comparison. The general contract
+ * is that this comparison should be reflexive, symmetric, and transitive.
+ * Also, no object reference other than null is equal to null.
+ *
+ * <p>The default implementation returns {@code true} only if {@code this ==
+ * o}. See <a href="{@docRoot}reference/java/lang/Object.html#writing_equals">Writing a correct
+ * {@code equals} method</a>
+ * if you intend implementing your own {@code equals} method.
+ *
+ * <p>The general contract for the {@code equals} and {@link
+ * #hashCode()} methods is that if {@code equals} returns {@code true} for
+ * any two objects, then {@code hashCode()} must return the same value for
+ * these objects. This means that subclasses of {@code Object} usually
+ * override either both methods or neither of them.
+ *
+ * @param o
+ * the object to compare this instance with.
+ * @return {@code true} if the specified object is equal to this {@code
+ * Object}; {@code false} otherwise.
+ * @see #hashCode
+ */
+ public boolean equals(Object o) {
+ return this == o;
+ }
+
+ /**
+ * Invoked when the garbage collector has detected that this instance is no longer reachable.
+ * The default implementation does nothing, but this method can be overridden to free resources.
+ *
+ * <p>Note that objects that override {@code finalize} are significantly more expensive than
+ * objects that don't. Finalizers may be run a long time after the object is no longer
+ * reachable, depending on memory pressure, so it's a bad idea to rely on them for cleanup.
+ * Note also that finalizers are run on a single VM-wide finalizer thread,
+ * so doing blocking work in a finalizer is a bad idea. A finalizer is usually only necessary
+ * for a class that has a native peer and needs to call a native method to destroy that peer.
+ * Even then, it's better to provide an explicit {@code close} method (and implement
+ * {@link java.io.Closeable}), and insist that callers manually dispose of instances. This
+ * works well for something like files, but less well for something like a {@code BigInteger}
+ * where typical calling code would have to deal with lots of temporaries. Unfortunately,
+ * code that creates lots of temporaries is the worst kind of code from the point of view of
+ * the single finalizer thread.
+ *
+ * <p>If you <i>must</i> use finalizers, consider at least providing your own
+ * {@link java.lang.ref.ReferenceQueue} and having your own thread process that queue.
+ *
+ * <p>Unlike constructors, finalizers are not automatically chained. You are responsible for
+ * calling {@code super.finalize()} yourself.
+ *
+ * <p>Uncaught exceptions thrown by finalizers are ignored and do not terminate the finalizer
+ * thread.
+ *
+ * See <i>Effective Java</i> Item 7, "Avoid finalizers" for more.
+ */
+ @FindBugsSuppressWarnings("FI_EMPTY")
+ protected void finalize() throws Throwable {
+ }
+
+ /**
+ * Returns the unique instance of {@link Class} that represents this
+ * object's class. Note that {@code getClass()} is a special case in that it
+ * actually returns {@code Class<? extends Foo>} where {@code Foo} is the
+ * erasure of the type of the expression {@code getClass()} was called upon.
+ * <p>
+ * As an example, the following code actually compiles, although one might
+ * think it shouldn't:
+ * <p>
+ * <pre>{@code
+ * List<Integer> l = new ArrayList<Integer>();
+ * Class<? extends List> c = l.getClass();}</pre>
+ *
+ * @return this object's {@code Class} instance.
+ */
+ public final Class<?> getClass() {
+ return shadow$_klass_;
+ }
+
+ /**
+ * Returns an integer hash code for this object. By contract, any two
+ * objects for which {@link #equals} returns {@code true} must return
+ * the same hash code value. This means that subclasses of {@code Object}
+ * usually override both methods or neither method.
+ *
+ * <p>Note that hash values must not change over time unless information used in equals
+ * comparisons also changes.
+ *
+ * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_hashCode">Writing a correct
+ * {@code hashCode} method</a>
+ * if you intend implementing your own {@code hashCode} method.
+ *
+ * @return this object's hash code.
+ * @see #equals
+ */
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
+ /**
+ * Causes a thread which is waiting on this object's monitor (by means of
+ * calling one of the {@code wait()} methods) to be woken up. If more than
+ * one thread is waiting, one of them is chosen at the discretion of the
+ * VM. The chosen thread will not run immediately. The thread
+ * that called {@code notify()} has to release the object's monitor first.
+ * Also, the chosen thread still has to compete against other threads that
+ * try to synchronize on the same object.
+ * <p>
+ * This method can only be invoked by a thread which owns this object's
+ * monitor. A thread becomes owner of an object's monitor
+ * </p>
+ * <ul>
+ * <li>by executing a synchronized method of that object;</li>
+ * <li>by executing the body of a {@code synchronized} statement that
+ * synchronizes on the object;</li>
+ * <li>by executing a synchronized static method if the object is of type
+ * {@code Class}.</li>
+ * </ul>
+ *
+ * @see #notifyAll
+ * @see #wait()
+ * @see #wait(long)
+ * @see #wait(long,int)
+ * @see java.lang.Thread
+ */
+ public final native void notify();
+
+ /**
+ * Causes all threads which are waiting on this object's monitor (by means
+ * of calling one of the {@code wait()} methods) to be woken up. The threads
+ * will not run immediately. The thread that called {@code notify()} has to
+ * release the object's monitor first. Also, the threads still have to
+ * compete against other threads that try to synchronize on the same object.
+ * <p>
+ * This method can only be invoked by a thread which owns this object's
+ * monitor. A thread becomes owner of an object's monitor
+ * </p>
+ * <ul>
+ * <li>by executing a synchronized method of that object;</li>
+ * <li>by executing the body of a {@code synchronized} statement that
+ * synchronizes on the object;</li>
+ * <li>by executing a synchronized static method if the object is of type
+ * {@code Class}.</li>
+ * </ul>
+ *
+ * @throws IllegalMonitorStateException
+ * if the thread calling this method is not the owner of this
+ * object's monitor.
+ * @see #notify
+ * @see #wait()
+ * @see #wait(long)
+ * @see #wait(long,int)
+ * @see java.lang.Thread
+ */
+ public final native void notifyAll();
+
+ /**
+ * Returns a string containing a concise, human-readable description of this
+ * object. Subclasses are encouraged to override this method and provide an
+ * implementation that takes into account the object's type and data. The
+ * default implementation is equivalent to the following expression:
+ * <pre>
+ * getClass().getName() + '@' + Integer.toHexString(hashCode())</pre>
+ * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_toString">Writing a useful
+ * {@code toString} method</a>
+ * if you intend implementing your own {@code toString} method.
+ *
+ * @return a printable representation of this object.
+ */
+ public String toString() {
+ return getClass().getName() + '@' + Integer.toHexString(hashCode());
+ }
+
+ /**
+ * Causes the calling thread to wait until another thread calls the {@code
+ * notify()} or {@code notifyAll()} method of this object. This method can
+ * only be invoked by a thread which owns this object's monitor; see
+ * {@link #notify()} on how a thread can become the owner of a monitor.
+ * <p>
+ * A waiting thread can be sent {@code interrupt()} to cause it to
+ * prematurely stop waiting, so {@code wait} should be called in a loop to
+ * check that the condition that has been waited for has been met before
+ * continuing.
+ * </p>
+ * <p>
+ * While the thread waits, it gives up ownership of this object's monitor.
+ * When it is notified (or interrupted), it re-acquires the monitor before
+ * it starts running.
+ * </p>
+ *
+ * @throws IllegalMonitorStateException
+ * if the thread calling this method is not the owner of this
+ * object's monitor.
+ * @throws InterruptedException
+ * if another thread interrupts this thread while it is waiting.
+ * @see #notify
+ * @see #notifyAll
+ * @see #wait(long)
+ * @see #wait(long,int)
+ * @see java.lang.Thread
+ */
+ public final native void wait() throws InterruptedException;
+
+ /**
+ * Causes the calling thread to wait until another thread calls the {@code
+ * notify()} or {@code notifyAll()} method of this object or until the
+ * specified timeout expires. This method can only be invoked by a thread
+ * which owns this object's monitor; see {@link #notify()} on how a thread
+ * can become the owner of a monitor.
+ * <p>
+ * A waiting thread can be sent {@code interrupt()} to cause it to
+ * prematurely stop waiting, so {@code wait} should be called in a loop to
+ * check that the condition that has been waited for has been met before
+ * continuing.
+ * </p>
+ * <p>
+ * While the thread waits, it gives up ownership of this object's monitor.
+ * When it is notified (or interrupted), it re-acquires the monitor before
+ * it starts running.
+ * </p>
+ *
+ * @param millis
+ * the maximum time to wait in milliseconds.
+ * @throws IllegalArgumentException
+ * if {@code millis < 0}.
+ * @throws IllegalMonitorStateException
+ * if the thread calling this method is not the owner of this
+ * object's monitor.
+ * @throws InterruptedException
+ * if another thread interrupts this thread while it is waiting.
+ * @see #notify
+ * @see #notifyAll
+ * @see #wait()
+ * @see #wait(long,int)
+ * @see java.lang.Thread
+ */
+ public final void wait(long millis) throws InterruptedException {
+ wait(millis, 0);
+ }
+
+ /**
+ * Causes the calling thread to wait until another thread calls the {@code
+ * notify()} or {@code notifyAll()} method of this object or until the
+ * specified timeout expires. This method can only be invoked by a thread
+ * that owns this object's monitor; see {@link #notify()} on how a thread
+ * can become the owner of a monitor.
+ * <p>
+ * A waiting thread can be sent {@code interrupt()} to cause it to
+ * prematurely stop waiting, so {@code wait} should be called in a loop to
+ * check that the condition that has been waited for has been met before
+ * continuing.
+ * </p>
+ * <p>
+ * While the thread waits, it gives up ownership of this object's monitor.
+ * When it is notified (or interrupted), it re-acquires the monitor before
+ * it starts running.
+ * </p>
+ *
+ * @param millis
+ * the maximum time to wait in milliseconds.
+ * @param nanos
+ * the fraction of a millisecond to wait, specified in
+ * nanoseconds.
+ * @throws IllegalArgumentException
+ * if {@code millis < 0}, {@code nanos < 0} or {@code nanos >
+ * 999999}.
+ * @throws IllegalMonitorStateException
+ * if the thread calling this method is not the owner of this
+ * object's monitor.
+ * @throws InterruptedException
+ * if another thread interrupts this thread while it is waiting.
+ * @see #notify
+ * @see #notifyAll
+ * @see #wait()
+ * @see #wait(long,int)
+ * @see java.lang.Thread
+ */
+ public final native void wait(long millis, int nanos) throws InterruptedException;
+}
diff --git a/libart/src/main/java/java/lang/String.java b/libart/src/main/java/java/lang/String.java
new file mode 100644
index 0000000..385f549
--- /dev/null
+++ b/libart/src/main/java/java/lang/String.java
@@ -0,0 +1,2011 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 java.lang;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.Charsets;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Formatter;
+import java.util.Locale;
+import java.util.regex.Pattern;
+import libcore.util.EmptyArray;
+
+/**
+ * An immutable sequence of characters/code units ({@code char}s). A
+ * {@code String} is represented by array of UTF-16 values, such that
+ * Unicode supplementary characters (code points) are stored/encoded as
+ * surrogate pairs via Unicode code units ({@code char}).
+ *
+ * <a name="backing_array"><h3>Backing Arrays</h3></a>
+ * This class is implemented using a char[]. The length of the array may exceed
+ * the length of the string. For example, the string "Hello" may be backed by
+ * the array {@code ['H', 'e', 'l', 'l', 'o', 'W'. 'o', 'r', 'l', 'd']} with
+ * offset 0 and length 5.
+ *
+ * <p>Multiple strings can share the same char[] because strings are immutable.
+ * The {@link #substring} method <strong>always</strong> returns a string that
+ * shares the backing array of its source string. Generally this is an
+ * optimization: fewer character arrays need to be allocated, and less copying
+ * is necessary. But this can also lead to unwanted heap retention. Taking a
+ * short substring of long string means that the long shared char[] won't be
+ * garbage until both strings are garbage. This typically happens when parsing
+ * small substrings out of a large input. To avoid this where necessary, call
+ * {@code new String(longString.subString(...))}. The string copy constructor
+ * always ensures that the backing array is no larger than necessary.
+ *
+ * @see StringBuffer
+ * @see StringBuilder
+ * @see Charset
+ * @since 1.0
+ */
+public final class String implements Serializable, Comparable<String>, CharSequence {
+
+ private static final long serialVersionUID = -6849794470754667710L;
+
+ private static final char REPLACEMENT_CHAR = (char) 0xfffd;
+
+ /**
+ * CaseInsensitiveComparator compares Strings ignoring the case of the
+ * characters.
+ */
+ private static final class CaseInsensitiveComparator implements
+ Comparator<String>, Serializable {
+ private static final long serialVersionUID = 8575799808933029326L;
+
+ /**
+ * Compare the two objects to determine the relative ordering.
+ *
+ * @param o1
+ * an Object to compare
+ * @param o2
+ * an Object to compare
+ * @return an int < 0 if object1 is less than object2, 0 if they are
+ * equal, and > 0 if object1 is greater
+ *
+ * @exception ClassCastException
+ * if objects are not the correct type
+ */
+ public int compare(String o1, String o2) {
+ return o1.compareToIgnoreCase(o2);
+ }
+ }
+
+ /**
+ * A comparator ignoring the case of the characters.
+ */
+ public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
+
+ private static final char[] ASCII;
+ static {
+ ASCII = new char[128];
+ for (int i = 0; i < ASCII.length; ++i) {
+ ASCII[i] = (char) i;
+ }
+ }
+
+ private final char[] value;
+
+ private final int offset;
+
+ private final int count;
+
+ private int hashCode;
+
+ /**
+ * Creates an empty string.
+ */
+ public String() {
+ value = EmptyArray.CHAR;
+ offset = 0;
+ count = 0;
+ }
+
+ /**
+ * Converts the byte array to a string using the system's
+ * {@link java.nio.charset.Charset#defaultCharset default charset}.
+ */
+ @FindBugsSuppressWarnings("DM_DEFAULT_ENCODING")
+ public String(byte[] data) {
+ this(data, 0, data.length);
+ }
+
+ /**
+ * Converts the byte array to a string, setting the high byte of every
+ * character to the specified value.
+ *
+ * @param data
+ * the byte array to convert to a string.
+ * @param high
+ * the high byte to use.
+ * @throws NullPointerException
+ * if {@code data == null}.
+ * @deprecated Use {@link #String(byte[])} or {@link #String(byte[], String)} instead.
+ */
+ @Deprecated
+ public String(byte[] data, int high) {
+ this(data, high, 0, data.length);
+ }
+
+ /**
+ * Converts a subsequence of the byte array to a string using the system's
+ * {@link java.nio.charset.Charset#defaultCharset default charset}.
+ *
+ * @throws NullPointerException
+ * if {@code data == null}.
+ * @throws IndexOutOfBoundsException
+ * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
+ */
+ public String(byte[] data, int offset, int byteCount) {
+ this(data, offset, byteCount, Charset.defaultCharset());
+ }
+
+ /**
+ * Converts the byte array to a string, setting the high byte of every
+ * character to {@code high}.
+ *
+ * @throws NullPointerException
+ * if {@code data == null}.
+ * @throws IndexOutOfBoundsException
+ * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
+ *
+ * @deprecated Use {@link #String(byte[], int, int)} instead.
+ */
+ @Deprecated
+ public String(byte[] data, int high, int offset, int byteCount) {
+ if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
+ throw failedBoundsCheck(data.length, offset, byteCount);
+ }
+ this.offset = 0;
+ this.value = new char[byteCount];
+ this.count = byteCount;
+ high <<= 8;
+ for (int i = 0; i < count; i++) {
+ value[i] = (char) (high + (data[offset++] & 0xff));
+ }
+ }
+
+ /**
+ * Converts the byte array to a string using the named charset.
+ *
+ * <p>The behavior when the bytes cannot be decoded by the named charset
+ * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
+ *
+ * @throws NullPointerException
+ * if {@code data == null}.
+ * @throws IndexOutOfBoundsException
+ * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
+ * @throws UnsupportedEncodingException
+ * if the named charset is not supported.
+ */
+ public String(byte[] data, int offset, int byteCount, String charsetName) throws UnsupportedEncodingException {
+ this(data, offset, byteCount, Charset.forNameUEE(charsetName));
+ }
+
+ /**
+ * Converts the byte array to a string using the named charset.
+ *
+ * <p>The behavior when the bytes cannot be decoded by the named charset
+ * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
+ *
+ * @throws NullPointerException
+ * if {@code data == null}.
+ * @throws UnsupportedEncodingException
+ * if {@code charsetName} is not supported.
+ */
+ public String(byte[] data, String charsetName) throws UnsupportedEncodingException {
+ this(data, 0, data.length, Charset.forNameUEE(charsetName));
+ }
+
+ /**
+ * Converts the byte array to a string using the given charset.
+ *
+ * <p>The behavior when the bytes cannot be decoded by the given charset
+ * is to replace malformed input and unmappable characters with the charset's default
+ * replacement string. Use {@link java.nio.charset.CharsetDecoder} for more control.
+ *
+ * @throws IndexOutOfBoundsException
+ * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
+ * @throws NullPointerException
+ * if {@code data == null}
+ *
+ * @since 1.6
+ */
+ public String(byte[] data, int offset, int byteCount, Charset charset) {
+ if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
+ throw failedBoundsCheck(data.length, offset, byteCount);
+ }
+
+ // We inline UTF-8, ISO-8859-1, and US-ASCII decoders for speed and because 'count' and
+ // 'value' are final.
+ String canonicalCharsetName = charset.name();
+ if (canonicalCharsetName.equals("UTF-8")) {
+ byte[] d = data;
+ char[] v = new char[byteCount];
+
+ int idx = offset;
+ int last = offset + byteCount;
+ int s = 0;
+outer:
+ while (idx < last) {
+ byte b0 = d[idx++];
+ if ((b0 & 0x80) == 0) {
+ // 0xxxxxxx
+ // Range: U-00000000 - U-0000007F
+ int val = b0 & 0xff;
+ v[s++] = (char) val;
+ } else if (((b0 & 0xe0) == 0xc0) || ((b0 & 0xf0) == 0xe0) ||
+ ((b0 & 0xf8) == 0xf0) || ((b0 & 0xfc) == 0xf8) || ((b0 & 0xfe) == 0xfc)) {
+ int utfCount = 1;
+ if ((b0 & 0xf0) == 0xe0) utfCount = 2;
+ else if ((b0 & 0xf8) == 0xf0) utfCount = 3;
+ else if ((b0 & 0xfc) == 0xf8) utfCount = 4;
+ else if ((b0 & 0xfe) == 0xfc) utfCount = 5;
+
+ // 110xxxxx (10xxxxxx)+
+ // Range: U-00000080 - U-000007FF (count == 1)
+ // Range: U-00000800 - U-0000FFFF (count == 2)
+ // Range: U-00010000 - U-001FFFFF (count == 3)
+ // Range: U-00200000 - U-03FFFFFF (count == 4)
+ // Range: U-04000000 - U-7FFFFFFF (count == 5)
+
+ if (idx + utfCount > last) {
+ v[s++] = REPLACEMENT_CHAR;
+ continue;
+ }
+
+ // Extract usable bits from b0
+ int val = b0 & (0x1f >> (utfCount - 1));
+ for (int i = 0; i < utfCount; ++i) {
+ byte b = d[idx++];
+ if ((b & 0xc0) != 0x80) {
+ v[s++] = REPLACEMENT_CHAR;
+ idx--; // Put the input char back
+ continue outer;
+ }
+ // Push new bits in from the right side
+ val <<= 6;
+ val |= b & 0x3f;
+ }
+
+ // Note: Java allows overlong char
+ // specifications To disallow, check that val
+ // is greater than or equal to the minimum
+ // value for each count:
+ //
+ // count min value
+ // ----- ----------
+ // 1 0x80
+ // 2 0x800
+ // 3 0x10000
+ // 4 0x200000
+ // 5 0x4000000
+
+ // Allow surrogate values (0xD800 - 0xDFFF) to
+ // be specified using 3-byte UTF values only
+ if ((utfCount != 2) && (val >= 0xD800) && (val <= 0xDFFF)) {
+ v[s++] = REPLACEMENT_CHAR;
+ continue;
+ }
+
+ // Reject chars greater than the Unicode maximum of U+10FFFF.
+ if (val > 0x10FFFF) {
+ v[s++] = REPLACEMENT_CHAR;
+ continue;
+ }
+
+ // Encode chars from U+10000 up as surrogate pairs
+ if (val < 0x10000) {
+ v[s++] = (char) val;
+ } else {
+ int x = val & 0xffff;
+ int u = (val >> 16) & 0x1f;
+ int w = (u - 1) & 0xffff;
+ int hi = 0xd800 | (w << 6) | (x >> 10);
+ int lo = 0xdc00 | (x & 0x3ff);
+ v[s++] = (char) hi;
+ v[s++] = (char) lo;
+ }
+ } else {
+ // Illegal values 0x8*, 0x9*, 0xa*, 0xb*, 0xfd-0xff
+ v[s++] = REPLACEMENT_CHAR;
+ }
+ }
+
+ if (s == byteCount) {
+ // We guessed right, so we can use our temporary array as-is.
+ this.offset = 0;
+ this.value = v;
+ this.count = s;
+ } else {
+ // Our temporary array was too big, so reallocate and copy.
+ this.offset = 0;
+ this.value = new char[s];
+ this.count = s;
+ System.arraycopy(v, 0, value, 0, s);
+ }
+ } else if (canonicalCharsetName.equals("ISO-8859-1")) {
+ this.offset = 0;
+ this.value = new char[byteCount];
+ this.count = byteCount;
+ Charsets.isoLatin1BytesToChars(data, offset, byteCount, value);
+ } else if (canonicalCharsetName.equals("US-ASCII")) {
+ this.offset = 0;
+ this.value = new char[byteCount];
+ this.count = byteCount;
+ Charsets.asciiBytesToChars(data, offset, byteCount, value);
+ } else {
+ CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount));
+ this.offset = 0;
+ this.count = cb.length();
+ if (count > 0) {
+ // We could use cb.array() directly, but that would mean we'd have to trust
+ // the CharsetDecoder doesn't hang on to the CharBuffer and mutate it later,
+ // which would break String's immutability guarantee. It would also tend to
+ // mean that we'd be wasting memory because CharsetDecoder doesn't trim the
+ // array. So we copy.
+ this.value = new char[count];
+ System.arraycopy(cb.array(), 0, value, 0, count);
+ } else {
+ this.value = EmptyArray.CHAR;
+ }
+ }
+ }
+
+ /**
+ * Converts the byte array to a String using the given charset.
+ *
+ * @throws NullPointerException if {@code data == null}
+ * @since 1.6
+ */
+ public String(byte[] data, Charset charset) {
+ this(data, 0, data.length, charset);
+ }
+
+ /**
+ * Initializes this string to contain the characters in the specified
+ * character array. Modifying the character array after creating the string
+ * has no effect on the string.
+ *
+ * @throws NullPointerException if {@code data == null}
+ */
+ public String(char[] data) {
+ this(data, 0, data.length);
+ }
+
+ /**
+ * Initializes this string to contain the specified characters in the
+ * character array. Modifying the character array after creating the string
+ * has no effect on the string.
+ *
+ * @throws NullPointerException
+ * if {@code data == null}.
+ * @throws IndexOutOfBoundsException
+ * if {@code charCount < 0 || offset < 0 || offset + charCount > data.length}
+ */
+ public String(char[] data, int offset, int charCount) {
+ if ((offset | charCount) < 0 || charCount > data.length - offset) {
+ throw failedBoundsCheck(data.length, offset, charCount);
+ }
+ this.offset = 0;
+ this.value = new char[charCount];
+ this.count = charCount;
+ System.arraycopy(data, offset, value, 0, count);
+ }
+
+ /*
+ * Internal version of the String(char[], int, int) constructor.
+ * Does not range check, null check, or copy the character array.
+ */
+ String(int offset, int charCount, char[] chars) {
+ this.value = chars;
+ this.offset = offset;
+ this.count = charCount;
+ }
+
+ /**
+ * Constructs a new string with the same sequence of characters as {@code
+ * toCopy}. The returned string's <a href="#backing_array">backing array</a>
+ * is no larger than necessary.
+ */
+ public String(String toCopy) {
+ value = (toCopy.value.length == toCopy.count)
+ ? toCopy.value
+ : Arrays.copyOfRange(toCopy.value, toCopy.offset, toCopy.offset + toCopy.length());
+ offset = 0;
+ count = value.length;
+ }
+
+ /**
+ * Creates a {@code String} from the contents of the specified
+ * {@code StringBuffer}.
+ */
+ public String(StringBuffer stringBuffer) {
+ offset = 0;
+ synchronized (stringBuffer) {
+ value = stringBuffer.shareValue();
+ count = stringBuffer.length();
+ }
+ }
+
+ /**
+ * Creates a {@code String} from the sub-array of Unicode code points.
+ *
+ * @throws NullPointerException
+ * if {@code codePoints == null}.
+ * @throws IllegalArgumentException
+ * if any of the elements of {@code codePoints} are not valid
+ * Unicode code points.
+ * @throws IndexOutOfBoundsException
+ * if {@code offset} or {@code count} are not within the bounds
+ * of {@code codePoints}.
+ * @since 1.5
+ */
+ public String(int[] codePoints, int offset, int count) {
+ if (codePoints == null) {
+ throw new NullPointerException("codePoints == null");
+ }
+ if ((offset | count) < 0 || count > codePoints.length - offset) {
+ throw failedBoundsCheck(codePoints.length, offset, count);
+ }
+ this.offset = 0;
+ this.value = new char[count * 2];
+ int end = offset + count;
+ int c = 0;
+ for (int i = offset; i < end; i++) {
+ c += Character.toChars(codePoints[i], this.value, c);
+ }
+ this.count = c;
+ }
+
+ /**
+ * Creates a {@code String} from the contents of the specified {@code
+ * StringBuilder}.
+ *
+ * @throws NullPointerException
+ * if {@code stringBuilder == null}.
+ * @since 1.5
+ */
+ public String(StringBuilder stringBuilder) {
+ if (stringBuilder == null) {
+ throw new NullPointerException("stringBuilder == null");
+ }
+ this.offset = 0;
+ this.count = stringBuilder.length();
+ this.value = new char[this.count];
+ stringBuilder.getChars(0, this.count, this.value, 0);
+ }
+
+ /**
+ * Returns the character at the specified offset in this string.
+ *
+ * @param index
+ * the zero-based index in this string.
+ * @return the character at the index.
+ * @throws IndexOutOfBoundsException
+ * if {@code index < 0} or {@code index >= length()}.
+ */
+ public char charAt(int index) {
+ if (index < 0 || index >= count) {
+ throw indexAndLength(index);
+ }
+ return value[offset + index];
+ }
+
+ private StringIndexOutOfBoundsException indexAndLength(int index) {
+ throw new StringIndexOutOfBoundsException(this, index);
+ }
+
+ private StringIndexOutOfBoundsException startEndAndLength(int start, int end) {
+ throw new StringIndexOutOfBoundsException(this, start, end - start);
+ }
+
+ private StringIndexOutOfBoundsException failedBoundsCheck(int arrayLength, int offset, int count) {
+ throw new StringIndexOutOfBoundsException(arrayLength, offset, count);
+ }
+
+ /**
+ * This isn't equivalent to either of ICU's u_foldCase case folds, and thus any of the Unicode
+ * case folds, but it's what the RI uses.
+ */
+ private char foldCase(char ch) {
+ if (ch < 128) {
+ if ('A' <= ch && ch <= 'Z') {
+ return (char) (ch + ('a' - 'A'));
+ }
+ return ch;
+ }
+ return Character.toLowerCase(Character.toUpperCase(ch));
+ }
+
+ /**
+ * Compares the specified string to this string using the Unicode values of
+ * the characters. Returns 0 if the strings contain the same characters in
+ * the same order. Returns a negative integer if the first non-equal
+ * character in this string has a Unicode value which is less than the
+ * Unicode value of the character at the same position in the specified
+ * string, or if this string is a prefix of the specified string. Returns a
+ * positive integer if the first non-equal character in this string has a
+ * Unicode value which is greater than the Unicode value of the character at
+ * the same position in the specified string, or if the specified string is
+ * a prefix of this string.
+ *
+ * @param string
+ * the string to compare.
+ * @return 0 if the strings are equal, a negative integer if this string is
+ * before the specified string, or a positive integer if this string
+ * is after the specified string.
+ * @throws NullPointerException
+ * if {@code string} is {@code null}.
+ */
+ public native int compareTo(String string);
+
+ /**
+ * Compares the specified string to this string using the Unicode values of
+ * the characters, ignoring case differences. Returns 0 if the strings
+ * contain the same characters in the same order. Returns a negative integer
+ * if the first non-equal character in this string has a Unicode value which
+ * is less than the Unicode value of the character at the same position in
+ * the specified string, or if this string is a prefix of the specified
+ * string. Returns a positive integer if the first non-equal character in
+ * this string has a Unicode value which is greater than the Unicode value
+ * of the character at the same position in the specified string, or if the
+ * specified string is a prefix of this string.
+ *
+ * @param string
+ * the string to compare.
+ * @return 0 if the strings are equal, a negative integer if this string is
+ * before the specified string, or a positive integer if this string
+ * is after the specified string.
+ * @throws NullPointerException
+ * if {@code string} is {@code null}.
+ */
+ public int compareToIgnoreCase(String string) {
+ int o1 = offset, o2 = string.offset, result;
+ int end = offset + (count < string.count ? count : string.count);
+ char c1, c2;
+ char[] target = string.value;
+ while (o1 < end) {
+ if ((c1 = value[o1++]) == (c2 = target[o2++])) {
+ continue;
+ }
+ c1 = foldCase(c1);
+ c2 = foldCase(c2);
+ if ((result = c1 - c2) != 0) {
+ return result;
+ }
+ }
+ return count - string.count;
+ }
+
+ /**
+ * Concatenates this string and the specified string.
+ *
+ * @param string
+ * the string to concatenate
+ * @return a new string which is the concatenation of this string and the
+ * specified string.
+ */
+ public String concat(String string) {
+ if (string.count > 0 && count > 0) {
+ char[] buffer = new char[count + string.count];
+ System.arraycopy(value, offset, buffer, 0, count);
+ System.arraycopy(string.value, string.offset, buffer, count, string.count);
+ return new String(0, buffer.length, buffer);
+ }
+ return count == 0 ? string : this;
+ }
+
+ /**
+ * Creates a new string containing the characters in the specified character
+ * array. Modifying the character array after creating the string has no
+ * effect on the string.
+ *
+ * @param data
+ * the array of characters.
+ * @return the new string.
+ * @throws NullPointerException
+ * if {@code data} is {@code null}.
+ */
+ public static String copyValueOf(char[] data) {
+ return new String(data, 0, data.length);
+ }
+
+ /**
+ * Creates a new string containing the specified characters in the character
+ * array. Modifying the character array after creating the string has no
+ * effect on the string.
+ *
+ * @param data
+ * the array of characters.
+ * @param start
+ * the starting offset in the character array.
+ * @param length
+ * the number of characters to use.
+ * @return the new string.
+ * @throws NullPointerException
+ * if {@code data} is {@code null}.
+ * @throws IndexOutOfBoundsException
+ * if {@code length < 0, start < 0} or {@code start + length >
+ * data.length}.
+ */
+ public static String copyValueOf(char[] data, int start, int length) {
+ return new String(data, start, length);
+ }
+
+ /**
+ * Compares the specified string to this string to determine if the
+ * specified string is a suffix.
+ *
+ * @param suffix
+ * the suffix to look for.
+ * @return {@code true} if the specified string is a suffix of this string,
+ * {@code false} otherwise.
+ * @throws NullPointerException
+ * if {@code suffix} is {@code null}.
+ */
+ public boolean endsWith(String suffix) {
+ return regionMatches(count - suffix.count, suffix, 0, suffix.count);
+ }
+
+ /**
+ * Compares the specified object to this string and returns true if they are
+ * equal. The object must be an instance of string with the same characters
+ * in the same order.
+ *
+ * @param other
+ * the object to compare.
+ * @return {@code true} if the specified object is equal to this string,
+ * {@code false} otherwise.
+ * @see #hashCode
+ */
+ @Override public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (other instanceof String) {
+ String s = (String)other;
+ int count = this.count;
+ if (s.count != count) {
+ return false;
+ }
+ // TODO: we want to avoid many boundchecks in the loop below
+ // for long Strings until we have array equality intrinsic.
+ // Bad benchmarks just push .equals without first getting a
+ // hashCode hit (unlike real world use in a Hashtable). Filter
+ // out these long strings here. When we get the array equality
+ // intrinsic then remove this use of hashCode.
+ if (hashCode() != s.hashCode()) {
+ return false;
+ }
+ char[] value1 = value;
+ int offset1 = offset;
+ char[] value2 = s.value;
+ int offset2 = s.offset;
+ for (int end = offset1 + count; offset1 < end; ) {
+ if (value1[offset1] != value2[offset2]) {
+ return false;
+ }
+ offset1++;
+ offset2++;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Compares the specified string to this string ignoring the case of the
+ * characters and returns true if they are equal.
+ *
+ * @param string
+ * the string to compare.
+ * @return {@code true} if the specified string is equal to this string,
+ * {@code false} otherwise.
+ */
+ @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
+ public boolean equalsIgnoreCase(String string) {
+ if (string == this) {
+ return true;
+ }
+ if (string == null || count != string.count) {
+ return false;
+ }
+ int o1 = offset, o2 = string.offset;
+ int end = offset + count;
+ char[] target = string.value;
+ while (o1 < end) {
+ char c1 = value[o1++];
+ char c2 = target[o2++];
+ if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Mangles this string into a byte array by stripping the high order bits from
+ * each character. Use {@link #getBytes()} or {@link #getBytes(String)} instead.
+ *
+ * @param start
+ * the starting offset of characters to copy.
+ * @param end
+ * the ending offset of characters to copy.
+ * @param data
+ * the destination byte array.
+ * @param index
+ * the starting offset in the destination byte array.
+ * @throws NullPointerException
+ * if {@code data} is {@code null}.
+ * @throws IndexOutOfBoundsException
+ * if {@code start < 0}, {@code end > length()}, {@code index <
+ * 0} or {@code end - start > data.length - index}.
+ * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)}
+ */
+ @Deprecated
+ public void getBytes(int start, int end, byte[] data, int index) {
+ // Note: last character not copied!
+ if (start >= 0 && start <= end && end <= count) {
+ end += offset;
+ try {
+ for (int i = offset + start; i < end; i++) {
+ data[index++] = (byte) value[i];
+ }
+ } catch (ArrayIndexOutOfBoundsException ignored) {
+ throw failedBoundsCheck(data.length, index, end - start);
+ }
+ } else {
+ throw startEndAndLength(start, end);
+ }
+ }
+
+ /**
+ * Returns a new byte array containing the characters of this string encoded using the
+ * system's {@link java.nio.charset.Charset#defaultCharset default charset}.
+ *
+ * <p>The behavior when this string cannot be represented in the system's default charset
+ * is unspecified. In practice, when the default charset is UTF-8 (as it is on Android),
+ * all strings can be encoded.
+ */
+ public byte[] getBytes() {
+ return getBytes(Charset.defaultCharset());
+ }
+
+ /**
+ * Returns a new byte array containing the characters of this string encoded using the
+ * named charset.
+ *
+ * <p>The behavior when this string cannot be represented in the named charset
+ * is unspecified. Use {@link java.nio.charset.CharsetEncoder} for more control.
+ *
+ * @throws UnsupportedEncodingException if the charset is not supported
+ */
+ public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
+ return getBytes(Charset.forNameUEE(charsetName));
+ }
+
+ /**
+ * Returns a new byte array containing the characters of this string encoded using the
+ * given charset.
+ *
+ * <p>The behavior when this string cannot be represented in the given charset
+ * is to replace malformed input and unmappable characters with the charset's default
+ * replacement byte array. Use {@link java.nio.charset.CharsetEncoder} for more control.
+ *
+ * @since 1.6
+ */
+ public byte[] getBytes(Charset charset) {
+ String canonicalCharsetName = charset.name();
+ if (canonicalCharsetName.equals("UTF-8")) {
+ return Charsets.toUtf8Bytes(value, offset, count);
+ } else if (canonicalCharsetName.equals("ISO-8859-1")) {
+ return Charsets.toIsoLatin1Bytes(value, offset, count);
+ } else if (canonicalCharsetName.equals("US-ASCII")) {
+ return Charsets.toAsciiBytes(value, offset, count);
+ } else if (canonicalCharsetName.equals("UTF-16BE")) {
+ return Charsets.toBigEndianUtf16Bytes(value, offset, count);
+ } else {
+ CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);
+ ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer());
+ byte[] bytes = new byte[buffer.limit()];
+ buffer.get(bytes);
+ return bytes;
+ }
+ }
+
+ /**
+ * Copies the specified characters in this string to the character array
+ * starting at the specified offset in the character array.
+ *
+ * @param start
+ * the starting offset of characters to copy.
+ * @param end
+ * the ending offset of characters to copy.
+ * @param buffer
+ * the destination character array.
+ * @param index
+ * the starting offset in the character array.
+ * @throws NullPointerException
+ * if {@code buffer} is {@code null}.
+ * @throws IndexOutOfBoundsException
+ * if {@code start < 0}, {@code end > length()}, {@code start >
+ * end}, {@code index < 0}, {@code end - start > buffer.length -
+ * index}
+ */
+ public void getChars(int start, int end, char[] buffer, int index) {
+ // Note: last character not copied!
+ if (start >= 0 && start <= end && end <= count) {
+ System.arraycopy(value, start + offset, buffer, index, end - start);
+ } else {
+ // We throw StringIndexOutOfBoundsException rather than System.arraycopy's AIOOBE.
+ throw startEndAndLength(start, end);
+ }
+ }
+
+ /**
+ * Version of getChars without bounds checks, for use by other classes
+ * within the java.lang package only. The caller is responsible for
+ * ensuring that start >= 0 && start <= end && end <= count.
+ */
+ void _getChars(int start, int end, char[] buffer, int index) {
+ // NOTE last character not copied!
+ System.arraycopy(value, start + offset, buffer, index, end - start);
+ }
+
+ @Override public int hashCode() {
+ int hash = hashCode;
+ if (hash == 0) {
+ if (count == 0) {
+ return 0;
+ }
+ final int end = count + offset;
+ final char[] chars = value;
+ for (int i = offset; i < end; ++i) {
+ hash = 31*hash + chars[i];
+ }
+ hashCode = hash;
+ }
+ return hash;
+ }
+
+ /**
+ * Searches in this string for the first index of the specified character.
+ * The search for the character starts at the beginning and moves towards
+ * the end of this string.
+ *
+ * @param c
+ * the character to find.
+ * @return the index in this string of the specified character, -1 if the
+ * character isn't found.
+ */
+ public int indexOf(int c) {
+ // TODO: just "return indexOf(c, 0);" when the JIT can inline that deep.
+ if (c > 0xffff) {
+ return indexOfSupplementary(c, 0);
+ }
+ return fastIndexOf(c, 0);
+ }
+
+ /**
+ * Searches in this string for the index of the specified character. The
+ * search for the character starts at the specified offset and moves towards
+ * the end of this string.
+ *
+ * @param c
+ * the character to find.
+ * @param start
+ * the starting offset.
+ * @return the index in this string of the specified character, -1 if the
+ * character isn't found.
+ */
+ public int indexOf(int c, int start) {
+ if (c > 0xffff) {
+ return indexOfSupplementary(c, start);
+ }
+ return fastIndexOf(c, start);
+ }
+
+ private native int fastIndexOf(int c, int start);
+
+ private int indexOfSupplementary(int c, int start) {
+ if (!Character.isSupplementaryCodePoint(c)) {
+ return -1;
+ }
+ char[] chars = Character.toChars(c);
+ String needle = new String(0, chars.length, chars);
+ return indexOf(needle, start);
+ }
+
+ /**
+ * Searches in this string for the first index of the specified string. The
+ * search for the string starts at the beginning and moves towards the end
+ * of this string.
+ *
+ * @param string
+ * the string to find.
+ * @return the index of the first character of the specified string in this
+ * string, -1 if the specified string is not a substring.
+ * @throws NullPointerException
+ * if {@code string} is {@code null}.
+ */
+ public int indexOf(String string) {
+ int start = 0;
+ int subCount = string.count;
+ int _count = count;
+ if (subCount > 0) {
+ if (subCount > _count) {
+ return -1;
+ }
+ char[] target = string.value;
+ int subOffset = string.offset;
+ char firstChar = target[subOffset];
+ int end = subOffset + subCount;
+ while (true) {
+ int i = indexOf(firstChar, start);
+ if (i == -1 || subCount + i > _count) {
+ return -1; // handles subCount > count || start >= count
+ }
+ int o1 = offset + i, o2 = subOffset;
+ char[] _value = value;
+ while (++o2 < end && _value[++o1] == target[o2]) {
+ // Intentionally empty
+ }
+ if (o2 == end) {
+ return i;
+ }
+ start = i + 1;
+ }
+ }
+ return start < _count ? start : _count;
+ }
+
+ /**
+ * Searches in this string for the index of the specified string. The search
+ * for the string starts at the specified offset and moves towards the end
+ * of this string.
+ *
+ * @param subString
+ * the string to find.
+ * @param start
+ * the starting offset.
+ * @return the index of the first character of the specified string in this
+ * string, -1 if the specified string is not a substring.
+ * @throws NullPointerException
+ * if {@code subString} is {@code null}.
+ */
+ public int indexOf(String subString, int start) {
+ if (start < 0) {
+ start = 0;
+ }
+ int subCount = subString.count;
+ int _count = count;
+ if (subCount > 0) {
+ if (subCount + start > _count) {
+ return -1;
+ }
+ char[] target = subString.value;
+ int subOffset = subString.offset;
+ char firstChar = target[subOffset];
+ int end = subOffset + subCount;
+ while (true) {
+ int i = indexOf(firstChar, start);
+ if (i == -1 || subCount + i > _count) {
+ return -1; // handles subCount > count || start >= count
+ }
+ int o1 = offset + i, o2 = subOffset;
+ char[] _value = value;
+ while (++o2 < end && _value[++o1] == target[o2]) {
+ // Intentionally empty
+ }
+ if (o2 == end) {
+ return i;
+ }
+ start = i + 1;
+ }
+ }
+ return start < _count ? start : _count;
+ }
+
+ /**
+ * Returns an interned string equal to this string. The VM maintains an internal set of
+ * unique strings. All string literals found in loaded classes'
+ * constant pools are automatically interned. Manually-interned strings are only weakly
+ * referenced, so calling {@code intern} won't lead to unwanted retention.
+ *
+ * <p>Interning is typically used because it guarantees that for interned strings
+ * {@code a} and {@code b}, {@code a.equals(b)} can be simplified to
+ * {@code a == b}. (This is not true of non-interned strings.)
+ *
+ * <p>Many applications find it simpler and more convenient to use an explicit
+ * {@link java.util.HashMap} to implement their own pools.
+ */
+ public native String intern();
+
+ /**
+ * Returns true if the length of this string is 0.
+ *
+ * @since 1.6
+ */
+ public boolean isEmpty() {
+ return count == 0;
+ }
+
+ /**
+ * Returns the last index of the code point {@code c}, or -1.
+ * The search for the character starts at the end and moves towards the
+ * beginning of this string.
+ */
+ public int lastIndexOf(int c) {
+ if (c > 0xffff) {
+ return lastIndexOfSupplementary(c, Integer.MAX_VALUE);
+ }
+ int _count = count;
+ int _offset = offset;
+ char[] _value = value;
+ for (int i = _offset + _count - 1; i >= _offset; --i) {
+ if (_value[i] == c) {
+ return i - _offset;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the last index of the code point {@code c}, or -1.
+ * The search for the character starts at offset {@code start} and moves towards
+ * the beginning of this string.
+ */
+ public int lastIndexOf(int c, int start) {
+ if (c > 0xffff) {
+ return lastIndexOfSupplementary(c, start);
+ }
+ int _count = count;
+ int _offset = offset;
+ char[] _value = value;
+ if (start >= 0) {
+ if (start >= _count) {
+ start = _count - 1;
+ }
+ for (int i = _offset + start; i >= _offset; --i) {
+ if (_value[i] == c) {
+ return i - _offset;
+ }
+ }
+ }
+ return -1;
+ }
+
+ private int lastIndexOfSupplementary(int c, int start) {
+ if (!Character.isSupplementaryCodePoint(c)) {
+ return -1;
+ }
+ char[] chars = Character.toChars(c);
+ String needle = new String(0, chars.length, chars);
+ return lastIndexOf(needle, start);
+ }
+
+ /**
+ * Searches in this string for the last index of the specified string. The
+ * search for the string starts at the end and moves towards the beginning
+ * of this string.
+ *
+ * @param string
+ * the string to find.
+ * @return the index of the first character of the specified string in this
+ * string, -1 if the specified string is not a substring.
+ * @throws NullPointerException
+ * if {@code string} is {@code null}.
+ */
+ public int lastIndexOf(String string) {
+ // Use count instead of count - 1 so lastIndexOf("") returns count
+ return lastIndexOf(string, count);
+ }
+
+ /**
+ * Searches in this string for the index of the specified string. The search
+ * for the string starts at the specified offset and moves towards the
+ * beginning of this string.
+ *
+ * @param subString
+ * the string to find.
+ * @param start
+ * the starting offset.
+ * @return the index of the first character of the specified string in this
+ * string , -1 if the specified string is not a substring.
+ * @throws NullPointerException
+ * if {@code subString} is {@code null}.
+ */
+ public int lastIndexOf(String subString, int start) {
+ int subCount = subString.count;
+ if (subCount <= count && start >= 0) {
+ if (subCount > 0) {
+ if (start > count - subCount) {
+ start = count - subCount;
+ }
+ // count and subCount are both >= 1
+ char[] target = subString.value;
+ int subOffset = subString.offset;
+ char firstChar = target[subOffset];
+ int end = subOffset + subCount;
+ while (true) {
+ int i = lastIndexOf(firstChar, start);
+ if (i == -1) {
+ return -1;
+ }
+ int o1 = offset + i, o2 = subOffset;
+ while (++o2 < end && value[++o1] == target[o2]) {
+ // Intentionally empty
+ }
+ if (o2 == end) {
+ return i;
+ }
+ start = i - 1;
+ }
+ }
+ return start < count ? start : count;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the number of characters in this string.
+ */
+ public int length() {
+ return count;
+ }
+
+ /**
+ * Compares the specified string to this string and compares the specified
+ * range of characters to determine if they are the same.
+ *
+ * @param thisStart
+ * the starting offset in this string.
+ * @param string
+ * the string to compare.
+ * @param start
+ * the starting offset in the specified string.
+ * @param length
+ * the number of characters to compare.
+ * @return {@code true} if the ranges of characters are equal, {@code false}
+ * otherwise
+ * @throws NullPointerException
+ * if {@code string} is {@code null}.
+ */
+ public boolean regionMatches(int thisStart, String string, int start, int length) {
+ if (string == null) {
+ throw new NullPointerException("string == null");
+ }
+ if (start < 0 || string.count - start < length) {
+ return false;
+ }
+ if (thisStart < 0 || count - thisStart < length) {
+ return false;
+ }
+ if (length <= 0) {
+ return true;
+ }
+ int o1 = offset + thisStart, o2 = string.offset + start;
+ char[] value1 = value;
+ char[] value2 = string.value;
+ for (int i = 0; i < length; ++i) {
+ if (value1[o1 + i] != value2[o2 + i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Compares the specified string to this string and compares the specified
+ * range of characters to determine if they are the same. When ignoreCase is
+ * true, the case of the characters is ignored during the comparison.
+ *
+ * @param ignoreCase
+ * specifies if case should be ignored.
+ * @param thisStart
+ * the starting offset in this string.
+ * @param string
+ * the string to compare.
+ * @param start
+ * the starting offset in the specified string.
+ * @param length
+ * the number of characters to compare.
+ * @return {@code true} if the ranges of characters are equal, {@code false}
+ * otherwise.
+ * @throws NullPointerException
+ * if {@code string} is {@code null}.
+ */
+ public boolean regionMatches(boolean ignoreCase, int thisStart, String string, int start, int length) {
+ if (!ignoreCase) {
+ return regionMatches(thisStart, string, start, length);
+ }
+ if (string == null) {
+ throw new NullPointerException("string == null");
+ }
+ if (thisStart < 0 || length > count - thisStart) {
+ return false;
+ }
+ if (start < 0 || length > string.count - start) {
+ return false;
+ }
+ thisStart += offset;
+ start += string.offset;
+ int end = thisStart + length;
+ char[] target = string.value;
+ while (thisStart < end) {
+ char c1 = value[thisStart++];
+ char c2 = target[start++];
+ if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Copies this string replacing occurrences of the specified character with
+ * another character.
+ *
+ * @param oldChar
+ * the character to replace.
+ * @param newChar
+ * the replacement character.
+ * @return a new string with occurrences of oldChar replaced by newChar.
+ */
+ public String replace(char oldChar, char newChar) {
+ char[] buffer = value;
+ int _offset = offset;
+ int _count = count;
+
+ int idx = _offset;
+ int last = _offset + _count;
+ boolean copied = false;
+ while (idx < last) {
+ if (buffer[idx] == oldChar) {
+ if (!copied) {
+ char[] newBuffer = new char[_count];
+ System.arraycopy(buffer, _offset, newBuffer, 0, _count);
+ buffer = newBuffer;
+ idx -= _offset;
+ last -= _offset;
+ copied = true;
+ }
+ buffer[idx] = newChar;
+ }
+ idx++;
+ }
+
+ return copied ? new String(0, count, buffer) : this;
+ }
+
+ /**
+ * Copies this string replacing occurrences of the specified target sequence
+ * with another sequence. The string is processed from the beginning to the
+ * end.
+ *
+ * @param target
+ * the sequence to replace.
+ * @param replacement
+ * the replacement sequence.
+ * @return the resulting string.
+ * @throws NullPointerException
+ * if {@code target} or {@code replacement} is {@code null}.
+ */
+ public String replace(CharSequence target, CharSequence replacement) {
+ if (target == null) {
+ throw new NullPointerException("target == null");
+ }
+ if (replacement == null) {
+ throw new NullPointerException("replacement == null");
+ }
+
+ String targetString = target.toString();
+ int matchStart = indexOf(targetString, 0);
+ if (matchStart == -1) {
+ // If there's nothing to replace, return the original string untouched.
+ return this;
+ }
+
+ String replacementString = replacement.toString();
+
+ // The empty target matches at the start and end and between each character.
+ int targetLength = targetString.length();
+ if (targetLength == 0) {
+ // The result contains the original 'count' characters, a copy of the
+ // replacement string before every one of those characters, and a final
+ // copy of the replacement string at the end.
+ int resultLength = count + (count + 1) * replacementString.length();
+ StringBuilder result = new StringBuilder(resultLength);
+ result.append(replacementString);
+ int end = offset + count;
+ for (int i = offset; i != end; ++i) {
+ result.append(value[i]);
+ result.append(replacementString);
+ }
+ return result.toString();
+ }
+
+ StringBuilder result = new StringBuilder(count);
+ int searchStart = 0;
+ do {
+ // Copy characters before the match...
+ result.append(value, offset + searchStart, matchStart - searchStart);
+ // Insert the replacement...
+ result.append(replacementString);
+ // And skip over the match...
+ searchStart = matchStart + targetLength;
+ } while ((matchStart = indexOf(targetString, searchStart)) != -1);
+ // Copy any trailing chars...
+ result.append(value, offset + searchStart, count - searchStart);
+ return result.toString();
+ }
+
+ /**
+ * Compares the specified string to this string to determine if the
+ * specified string is a prefix.
+ *
+ * @param prefix
+ * the string to look for.
+ * @return {@code true} if the specified string is a prefix of this string,
+ * {@code false} otherwise
+ * @throws NullPointerException
+ * if {@code prefix} is {@code null}.
+ */
+ public boolean startsWith(String prefix) {
+ return startsWith(prefix, 0);
+ }
+
+ /**
+ * Compares the specified string to this string, starting at the specified
+ * offset, to determine if the specified string is a prefix.
+ *
+ * @param prefix
+ * the string to look for.
+ * @param start
+ * the starting offset.
+ * @return {@code true} if the specified string occurs in this string at the
+ * specified offset, {@code false} otherwise.
+ * @throws NullPointerException
+ * if {@code prefix} is {@code null}.
+ */
+ public boolean startsWith(String prefix, int start) {
+ return regionMatches(start, prefix, 0, prefix.count);
+ }
+
+ /**
+ * Returns a string containing a suffix of this string. The returned string
+ * shares this string's <a href="#backing_array">backing array</a>.
+ *
+ * @param start
+ * the offset of the first character.
+ * @return a new string containing the characters from start to the end of
+ * the string.
+ * @throws IndexOutOfBoundsException
+ * if {@code start < 0} or {@code start > length()}.
+ */
+ public String substring(int start) {
+ if (start == 0) {
+ return this;
+ }
+ if (start >= 0 && start <= count) {
+ return new String(offset + start, count - start, value);
+ }
+ throw indexAndLength(start);
+ }
+
+ /**
+ * Returns a string containing a subsequence of characters from this string.
+ * The returned string shares this string's <a href="#backing_array">backing
+ * array</a>.
+ *
+ * @param start
+ * the offset of the first character.
+ * @param end
+ * the offset one past the last character.
+ * @return a new string containing the characters from start to end - 1
+ * @throws IndexOutOfBoundsException
+ * if {@code start < 0}, {@code start > end} or {@code end >
+ * length()}.
+ */
+ public String substring(int start, int end) {
+ if (start == 0 && end == count) {
+ return this;
+ }
+ // NOTE last character not copied!
+ // Fast range check.
+ if (start >= 0 && start <= end && end <= count) {
+ return new String(offset + start, end - start, value);
+ }
+ throw startEndAndLength(start, end);
+ }
+
+ /**
+ * Returns a new {@code char} array containing a copy of the characters in this string.
+ * This is expensive and rarely useful. If you just want to iterate over the characters in
+ * the string, use {@link #charAt} instead.
+ */
+ public char[] toCharArray() {
+ char[] buffer = new char[count];
+ System.arraycopy(value, offset, buffer, 0, count);
+ return buffer;
+ }
+
+ /**
+ * Converts this string to lower case, using the rules of the user's default locale.
+ * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
+ *
+ * @return a new lower case string, or {@code this} if it's already all lower case.
+ */
+ public String toLowerCase() {
+ return CaseMapper.toLowerCase(Locale.getDefault(), this, value, offset, count);
+ }
+
+ /**
+ * Converts this string to lower case, using the rules of {@code locale}.
+ *
+ * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
+ * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
+ * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
+ * correct case mapping of Greek characters: any locale will do.
+ *
+ * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
+ * for full details of context- and language-specific special cases.
+ *
+ * @return a new lower case string, or {@code this} if it's already all lower case.
+ */
+ public String toLowerCase(Locale locale) {
+ return CaseMapper.toLowerCase(locale, this, value, offset, count);
+ }
+
+ /**
+ * Returns this string.
+ */
+ @Override
+ public String toString() {
+ return this;
+ }
+
+ /**
+ * Converts this this string to upper case, using the rules of the user's default locale.
+ * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
+ *
+ * @return a new upper case string, or {@code this} if it's already all upper case.
+ */
+ public String toUpperCase() {
+ return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count);
+ }
+
+ /**
+ * Converts this this string to upper case, using the rules of {@code locale}.
+ *
+ * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
+ * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
+ * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
+ * correct case mapping of Greek characters: any locale will do.
+ *
+ * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
+ * for full details of context- and language-specific special cases.
+ *
+ * @return a new upper case string, or {@code this} if it's already all upper case.
+ */
+ public String toUpperCase(Locale locale) {
+ return CaseMapper.toUpperCase(locale, this, value, offset, count);
+ }
+
+ /**
+ * Copies this string removing white space characters from the beginning and
+ * end of the string.
+ *
+ * @return a new string with characters <code><= \\u0020</code> removed from
+ * the beginning and the end.
+ */
+ public String trim() {
+ int start = offset, last = offset + count - 1;
+ int end = last;
+ while ((start <= end) && (value[start] <= ' ')) {
+ start++;
+ }
+ while ((end >= start) && (value[end] <= ' ')) {
+ end--;
+ }
+ if (start == offset && end == last) {
+ return this;
+ }
+ return new String(start, end - start + 1, value);
+ }
+
+ /**
+ * Creates a new string containing the characters in the specified character
+ * array. Modifying the character array after creating the string has no
+ * effect on the string.
+ *
+ * @param data
+ * the array of characters.
+ * @return the new string.
+ * @throws NullPointerException
+ * if {@code data} is {@code null}.
+ */
+ public static String valueOf(char[] data) {
+ return new String(data, 0, data.length);
+ }
+
+ /**
+ * Creates a new string containing the specified characters in the character
+ * array. Modifying the character array after creating the string has no
+ * effect on the string.
+ *
+ * @param data
+ * the array of characters.
+ * @param start
+ * the starting offset in the character array.
+ * @param length
+ * the number of characters to use.
+ * @return the new string.
+ * @throws IndexOutOfBoundsException
+ * if {@code length < 0}, {@code start < 0} or {@code start +
+ * length > data.length}
+ * @throws NullPointerException
+ * if {@code data} is {@code null}.
+ */
+ public static String valueOf(char[] data, int start, int length) {
+ return new String(data, start, length);
+ }
+
+ /**
+ * Converts the specified character to its string representation.
+ *
+ * @param value
+ * the character.
+ * @return the character converted to a string.
+ */
+ public static String valueOf(char value) {
+ String s;
+ if (value < 128) {
+ s = new String(value, 1, ASCII);
+ } else {
+ s = new String(0, 1, new char[] { value });
+ }
+ s.hashCode = value;
+ return s;
+ }
+
+ /**
+ * Converts the specified double to its string representation.
+ *
+ * @param value
+ * the double.
+ * @return the double converted to a string.
+ */
+ public static String valueOf(double value) {
+ return Double.toString(value);
+ }
+
+ /**
+ * Converts the specified float to its string representation.
+ *
+ * @param value
+ * the float.
+ * @return the float converted to a string.
+ */
+ public static String valueOf(float value) {
+ return Float.toString(value);
+ }
+
+ /**
+ * Converts the specified integer to its string representation.
+ *
+ * @param value
+ * the integer.
+ * @return the integer converted to a string.
+ */
+ public static String valueOf(int value) {
+ return Integer.toString(value);
+ }
+
+ /**
+ * Converts the specified long to its string representation.
+ *
+ * @param value
+ * the long.
+ * @return the long converted to a string.
+ */
+ public static String valueOf(long value) {
+ return Long.toString(value);
+ }
+
+ /**
+ * Converts the specified object to its string representation. If the object
+ * is null return the string {@code "null"}, otherwise use {@code
+ * toString()} to get the string representation.
+ *
+ * @param value
+ * the object.
+ * @return the object converted to a string, or the string {@code "null"}.
+ */
+ public static String valueOf(Object value) {
+ return value != null ? value.toString() : "null";
+ }
+
+ /**
+ * Converts the specified boolean to its string representation. When the
+ * boolean is {@code true} return {@code "true"}, otherwise return {@code
+ * "false"}.
+ *
+ * @param value
+ * the boolean.
+ * @return the boolean converted to a string.
+ */
+ public static String valueOf(boolean value) {
+ return value ? "true" : "false";
+ }
+
+ /**
+ * Returns whether the characters in the StringBuffer {@code strbuf} are the
+ * same as those in this string.
+ *
+ * @param strbuf
+ * the StringBuffer to compare this string to.
+ * @return {@code true} if the characters in {@code strbuf} are identical to
+ * those in this string. If they are not, {@code false} will be
+ * returned.
+ * @throws NullPointerException
+ * if {@code strbuf} is {@code null}.
+ * @since 1.4
+ */
+ public boolean contentEquals(StringBuffer strbuf) {
+ synchronized (strbuf) {
+ int size = strbuf.length();
+ if (count != size) {
+ return false;
+ }
+ return regionMatches(0, new String(0, size, strbuf.getValue()), 0,
+ size);
+ }
+ }
+
+ /**
+ * Compares a {@code CharSequence} to this {@code String} to determine if
+ * their contents are equal.
+ *
+ * @param cs
+ * the character sequence to compare to.
+ * @return {@code true} if equal, otherwise {@code false}
+ * @since 1.5
+ */
+ public boolean contentEquals(CharSequence cs) {
+ if (cs == null) {
+ throw new NullPointerException("cs == null");
+ }
+
+ int len = cs.length();
+
+ if (len != count) {
+ return false;
+ }
+
+ if (len == 0 && count == 0) {
+ return true; // since both are empty strings
+ }
+
+ return regionMatches(0, cs.toString(), 0, len);
+ }
+
+ /**
+ * Tests whether this string matches the given {@code regularExpression}. This method returns
+ * true only if the regular expression matches the <i>entire</i> input string. A common mistake is
+ * to assume that this method behaves like {@link #contains}; if you want to match anywhere
+ * within the input string, you need to add {@code .*} to the beginning and end of your
+ * regular expression. See {@link Pattern#matches}.
+ *
+ * <p>If the same regular expression is to be used for multiple operations, it may be more
+ * efficient to reuse a compiled {@code Pattern}.
+ *
+ * @throws PatternSyntaxException
+ * if the syntax of the supplied regular expression is not
+ * valid.
+ * @throws NullPointerException if {@code regularExpression == null}
+ * @since 1.4
+ */
+ public boolean matches(String regularExpression) {
+ return Pattern.matches(regularExpression, this);
+ }
+
+ /**
+ * Replaces all matches for {@code regularExpression} within this string with the given
+ * {@code replacement}.
+ * See {@link Pattern} for regular expression syntax.
+ *
+ * <p>If the same regular expression is to be used for multiple operations, it may be more
+ * efficient to reuse a compiled {@code Pattern}.
+ *
+ * @throws PatternSyntaxException
+ * if the syntax of the supplied regular expression is not
+ * valid.
+ * @throws NullPointerException if {@code regularExpression == null}
+ * @see Pattern
+ * @since 1.4
+ */
+ public String replaceAll(String regularExpression, String replacement) {
+ return Pattern.compile(regularExpression).matcher(this).replaceAll(replacement);
+ }
+
+ /**
+ * Replaces the first match for {@code regularExpression} within this string with the given
+ * {@code replacement}.
+ * See {@link Pattern} for regular expression syntax.
+ *
+ * <p>If the same regular expression is to be used for multiple operations, it may be more
+ * efficient to reuse a compiled {@code Pattern}.
+ *
+ * @throws PatternSyntaxException
+ * if the syntax of the supplied regular expression is not
+ * valid.
+ * @throws NullPointerException if {@code regularExpression == null}
+ * @see Pattern
+ * @since 1.4
+ */
+ public String replaceFirst(String regularExpression, String replacement) {
+ return Pattern.compile(regularExpression).matcher(this).replaceFirst(replacement);
+ }
+
+ /**
+ * Splits this string using the supplied {@code regularExpression}.
+ * Equivalent to {@code split(regularExpression, 0)}.
+ * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
+ * See {@link Pattern} for regular expression syntax.
+ *
+ * <p>If the same regular expression is to be used for multiple operations, it may be more
+ * efficient to reuse a compiled {@code Pattern}.
+ *
+ * @throws NullPointerException if {@code regularExpression == null}
+ * @throws PatternSyntaxException
+ * if the syntax of the supplied regular expression is not
+ * valid.
+ * @see Pattern
+ * @since 1.4
+ */
+ public String[] split(String regularExpression) {
+ return split(regularExpression, 0);
+ }
+
+ /**
+ * Splits this string using the supplied {@code regularExpression}.
+ * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
+ * See {@link Pattern} for regular expression syntax.
+ *
+ * <p>If the same regular expression is to be used for multiple operations, it may be more
+ * efficient to reuse a compiled {@code Pattern}.
+ *
+ * @throws NullPointerException if {@code regularExpression == null}
+ * @throws PatternSyntaxException
+ * if the syntax of the supplied regular expression is not
+ * valid.
+ * @since 1.4
+ */
+ public String[] split(String regularExpression, int limit) {
+ String[] result = java.util.regex.Splitter.fastSplit(regularExpression, this, limit);
+ return result != null ? result : Pattern.compile(regularExpression).split(this, limit);
+ }
+
+ /**
+ * Has the same result as the substring function, but is present so that
+ * string may implement the CharSequence interface.
+ *
+ * @param start
+ * the offset the first character.
+ * @param end
+ * the offset of one past the last character to include.
+ * @return the subsequence requested.
+ * @throws IndexOutOfBoundsException
+ * if {@code start < 0}, {@code end < 0}, {@code start > end} or
+ * {@code end > length()}.
+ * @see java.lang.CharSequence#subSequence(int, int)
+ * @since 1.4
+ */
+ public CharSequence subSequence(int start, int end) {
+ return substring(start, end);
+ }
+
+ /**
+ * Returns the Unicode code point at the given {@code index}.
+ *
+ * @throws IndexOutOfBoundsException if {@code index < 0 || index >= length()}
+ * @see Character#codePointAt(char[], int, int)
+ * @since 1.5
+ */
+ public int codePointAt(int index) {
+ if (index < 0 || index >= count) {
+ throw indexAndLength(index);
+ }
+ return Character.codePointAt(value, offset + index, offset + count);
+ }
+
+ /**
+ * Returns the Unicode code point that precedes the given {@code index}.
+ *
+ * @throws IndexOutOfBoundsException if {@code index < 1 || index > length()}
+ * @see Character#codePointBefore(char[], int, int)
+ * @since 1.5
+ */
+ public int codePointBefore(int index) {
+ if (index < 1 || index > count) {
+ throw indexAndLength(index);
+ }
+ return Character.codePointBefore(value, offset + index, offset);
+ }
+
+ /**
+ * Calculates the number of Unicode code points between {@code start}
+ * and {@code end}.
+ *
+ * @param start
+ * the inclusive beginning index of the subsequence.
+ * @param end
+ * the exclusive end index of the subsequence.
+ * @return the number of Unicode code points in the subsequence.
+ * @throws IndexOutOfBoundsException
+ * if {@code start < 0 || end > length() || start > end}
+ * @see Character#codePointCount(CharSequence, int, int)
+ * @since 1.5
+ */
+ public int codePointCount(int start, int end) {
+ if (start < 0 || end > count || start > end) {
+ throw startEndAndLength(start, end);
+ }
+ return Character.codePointCount(value, offset + start, end - start);
+ }
+
+ /**
+ * Determines if this {@code String} contains the sequence of characters in
+ * the {@code CharSequence} passed.
+ *
+ * @param cs
+ * the character sequence to search for.
+ * @return {@code true} if the sequence of characters are contained in this
+ * string, otherwise {@code false}.
+ * @since 1.5
+ */
+ public boolean contains(CharSequence cs) {
+ if (cs == null) {
+ throw new NullPointerException("cs == null");
+ }
+ return indexOf(cs.toString()) >= 0;
+ }
+
+ /**
+ * Returns the index within this object that is offset from {@code index} by
+ * {@code codePointOffset} code points.
+ *
+ * @param index
+ * the index within this object to calculate the offset from.
+ * @param codePointOffset
+ * the number of code points to count.
+ * @return the index within this object that is the offset.
+ * @throws IndexOutOfBoundsException
+ * if {@code index} is negative or greater than {@code length()}
+ * or if there aren't enough code points before or after {@code
+ * index} to match {@code codePointOffset}.
+ * @since 1.5
+ */
+ public int offsetByCodePoints(int index, int codePointOffset) {
+ int s = index + offset;
+ int r = Character.offsetByCodePoints(value, offset, count, s, codePointOffset);
+ return r - offset;
+ }
+
+ /**
+ * Returns a localized formatted string, using the supplied format and arguments,
+ * using the user's default locale.
+ *
+ * <p>If you're formatting a string other than for human
+ * consumption, you should use the {@code format(Locale, String, Object...)}
+ * overload and supply {@code Locale.US}. See
+ * "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
+ *
+ * @param format the format string (see {@link java.util.Formatter#format})
+ * @param args
+ * the list of arguments passed to the formatter. If there are
+ * more arguments than required by {@code format},
+ * additional arguments are ignored.
+ * @return the formatted string.
+ * @throws NullPointerException if {@code format == null}
+ * @throws java.util.IllegalFormatException
+ * if the format is invalid.
+ * @since 1.5
+ */
+ public static String format(String format, Object... args) {
+ return format(Locale.getDefault(), format, args);
+ }
+
+ /**
+ * Returns a formatted string, using the supplied format and arguments,
+ * localized to the given locale.
+ *
+ * @param locale
+ * the locale to apply; {@code null} value means no localization.
+ * @param format the format string (see {@link java.util.Formatter#format})
+ * @param args
+ * the list of arguments passed to the formatter. If there are
+ * more arguments than required by {@code format},
+ * additional arguments are ignored.
+ * @return the formatted string.
+ * @throws NullPointerException if {@code format == null}
+ * @throws java.util.IllegalFormatException
+ * if the format is invalid.
+ * @since 1.5
+ */
+ public static String format(Locale locale, String format, Object... args) {
+ if (format == null) {
+ throw new NullPointerException("format == null");
+ }
+ int bufferSize = format.length() + (args == null ? 0 : args.length * 10);
+ Formatter f = new Formatter(new StringBuilder(bufferSize), locale);
+ return f.format(format, args).toString();
+ }
+
+ /*
+ * An implementation of a String.indexOf that is supposed to perform
+ * substantially better than the default algorithm if the "needle" (the
+ * subString being searched for) is a constant string.
+ *
+ * For example, a JIT, upon encountering a call to String.indexOf(String),
+ * where the needle is a constant string, may compute the values cache, md2
+ * and lastChar, and change the call to the following method.
+ */
+ @FindBugsSuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
+ @SuppressWarnings("unused")
+ private static int indexOf(String haystackString, String needleString,
+ int cache, int md2, char lastChar) {
+ char[] haystack = haystackString.value;
+ int haystackOffset = haystackString.offset;
+ int haystackLength = haystackString.count;
+ char[] needle = needleString.value;
+ int needleOffset = needleString.offset;
+ int needleLength = needleString.count;
+ int needleLengthMinus1 = needleLength - 1;
+ int haystackEnd = haystackOffset + haystackLength;
+ outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
+ if (lastChar == haystack[i]) {
+ for (int j = 0; j < needleLengthMinus1; ++j) {
+ if (needle[j + needleOffset] != haystack[i + j
+ - needleLengthMinus1]) {
+ int skip = 1;
+ if ((cache & (1 << haystack[i])) == 0) {
+ skip += j;
+ }
+ i += Math.max(md2, skip);
+ continue outer_loop;
+ }
+ }
+ return i - needleLengthMinus1 - haystackOffset;
+ }
+
+ if ((cache & (1 << haystack[i])) == 0) {
+ i += needleLengthMinus1;
+ }
+ i++;
+ }
+ return -1;
+ }
+}
diff --git a/libart/src/main/java/java/lang/Thread.java b/libart/src/main/java/java/lang/Thread.java
new file mode 100644
index 0000000..5c81e36
--- /dev/null
+++ b/libart/src/main/java/java/lang/Thread.java
@@ -0,0 +1,1267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang;
+
+import dalvik.system.VMStack;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import libcore.util.EmptyArray;
+
+/**
+ * A {@code Thread} is a concurrent unit of execution. It has its own call stack
+ * for methods being invoked, their arguments and local variables. Each application
+ * has at least one thread running when it is started, the main thread, in the main
+ * {@link ThreadGroup}. The runtime keeps its own threads in the system thread
+ * group.
+ *
+ * <p>There are two ways to execute code in a new thread.
+ * You can either subclass {@code Thread} and overriding its {@link #run()} method,
+ * or construct a new {@code Thread} and pass a {@link Runnable} to the constructor.
+ * In either case, the {@link #start()} method must be called to actually execute
+ * the new {@code Thread}.
+ *
+ * <p>Each {@code Thread} has an integer priority that affect how the thread is
+ * scheduled by the OS. A new thread inherits the priority of its parent.
+ * A thread's priority can be set using the {@link #setPriority(int)} method.
+ */
+public class Thread implements Runnable {
+ private static final int NANOS_PER_MILLI = 1000000;
+
+ /** Park states */
+ private static class ParkState {
+ /** park state indicating unparked */
+ private static final int UNPARKED = 1;
+
+ /** park state indicating preemptively unparked */
+ private static final int PREEMPTIVELY_UNPARKED = 2;
+
+ /** park state indicating parked */
+ private static final int PARKED = 3;
+ }
+
+ /**
+ * A representation of a thread's state. A given thread may only be in one
+ * state at a time.
+ */
+ public enum State {
+ /**
+ * The thread has been created, but has never been started.
+ */
+ NEW,
+ /**
+ * The thread may be run.
+ */
+ RUNNABLE,
+ /**
+ * The thread is blocked and waiting for a lock.
+ */
+ BLOCKED,
+ /**
+ * The thread is waiting.
+ */
+ WAITING,
+ /**
+ * The thread is waiting for a specified amount of time.
+ */
+ TIMED_WAITING,
+ /**
+ * The thread has been terminated.
+ */
+ TERMINATED
+ }
+
+ /**
+ * The maximum priority value allowed for a thread.
+ * This corresponds to (but does not have the same value as)
+ * {@code android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY}.
+ */
+ public static final int MAX_PRIORITY = 10;
+
+ /**
+ * The minimum priority value allowed for a thread.
+ * This corresponds to (but does not have the same value as)
+ * {@code android.os.Process.THREAD_PRIORITY_LOWEST}.
+ */
+ public static final int MIN_PRIORITY = 1;
+
+ /**
+ * The normal (default) priority value assigned to the main thread.
+ * This corresponds to (but does not have the same value as)
+ * {@code android.os.Process.THREAD_PRIORITY_DEFAULT}.
+
+ */
+ public static final int NORM_PRIORITY = 5;
+
+ /* some of these are accessed directly by the VM; do not rename them */
+ private volatile int nativePeer;
+ volatile ThreadGroup group;
+ volatile boolean daemon;
+ volatile String name;
+ volatile int priority;
+ volatile long stackSize;
+ Runnable target;
+ private static int count = 0;
+
+ /**
+ * Holds the thread's ID. We simply count upwards, so
+ * each Thread has a unique ID.
+ */
+ private long id;
+
+ /**
+ * Normal thread local values.
+ */
+ ThreadLocal.Values localValues;
+
+ /**
+ * Inheritable thread local values.
+ */
+ ThreadLocal.Values inheritableValues;
+
+ /** Callbacks to run on interruption. */
+ private final List<Runnable> interruptActions = new ArrayList<Runnable>();
+
+ /**
+ * Holds the class loader for this Thread, in case there is one.
+ */
+ private ClassLoader contextClassLoader;
+
+ /**
+ * Holds the handler for uncaught exceptions in this Thread,
+ * in case there is one.
+ */
+ private UncaughtExceptionHandler uncaughtHandler;
+
+ /**
+ * Holds the default handler for uncaught exceptions, in case there is one.
+ */
+ private static UncaughtExceptionHandler defaultUncaughtHandler;
+
+ /**
+ * Reflects whether this Thread has already been started. A Thread
+ * can only be started once (no recycling). Also, we need it to deduce
+ * the proper Thread status.
+ */
+ boolean hasBeenStarted = false;
+
+ /** the park state of the thread */
+ private int parkState = ParkState.UNPARKED;
+
+ /**
+ * The synchronization object responsible for this thread's join/sleep/park operations.
+ */
+ private final Object lock = new Object();
+
+ /** Looked up reflectively and used by java.util.concurrent.locks.LockSupport. */
+ private Object parkBlocker;
+
+ /**
+ * Constructs a new {@code Thread} with no {@code Runnable} object and a
+ * newly generated name. The new {@code Thread} will belong to the same
+ * {@code ThreadGroup} as the {@code Thread} calling this constructor.
+ *
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread() {
+ create(null, null, null, 0);
+ }
+
+ /**
+ * Constructs a new {@code Thread} with a {@code Runnable} object and a
+ * newly generated name. The new {@code Thread} will belong to the same
+ * {@code ThreadGroup} as the {@code Thread} calling this constructor.
+ *
+ * @param runnable
+ * a {@code Runnable} whose method <code>run</code> will be
+ * executed by the new {@code Thread}
+ *
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(Runnable runnable) {
+ create(null, runnable, null, 0);
+ }
+
+ /**
+ * Constructs a new {@code Thread} with a {@code Runnable} object and name
+ * provided. The new {@code Thread} will belong to the same {@code
+ * ThreadGroup} as the {@code Thread} calling this constructor.
+ *
+ * @param runnable
+ * a {@code Runnable} whose method <code>run</code> will be
+ * executed by the new {@code Thread}
+ * @param threadName
+ * the name for the {@code Thread} being created
+ *
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(Runnable runnable, String threadName) {
+ if (threadName == null) {
+ throw new NullPointerException("threadName == null");
+ }
+
+ create(null, runnable, threadName, 0);
+ }
+
+ /**
+ * Constructs a new {@code Thread} with no {@code Runnable} object and the
+ * name provided. The new {@code Thread} will belong to the same {@code
+ * ThreadGroup} as the {@code Thread} calling this constructor.
+ *
+ * @param threadName
+ * the name for the {@code Thread} being created
+ *
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ *
+ */
+ public Thread(String threadName) {
+ if (threadName == null) {
+ throw new NullPointerException("threadName == null");
+ }
+
+ create(null, null, threadName, 0);
+ }
+
+ /**
+ * Constructs a new {@code Thread} with a {@code Runnable} object and a
+ * newly generated name. The new {@code Thread} will belong to the {@code
+ * ThreadGroup} passed as parameter.
+ *
+ * @param group
+ * {@code ThreadGroup} to which the new {@code Thread} will
+ * belong
+ * @param runnable
+ * a {@code Runnable} whose method <code>run</code> will be
+ * executed by the new {@code Thread}
+ * @throws IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(ThreadGroup group, Runnable runnable) {
+ create(group, runnable, null, 0);
+ }
+
+ /**
+ * Constructs a new {@code Thread} with a {@code Runnable} object, the given
+ * name and belonging to the {@code ThreadGroup} passed as parameter.
+ *
+ * @param group
+ * ThreadGroup to which the new {@code Thread} will belong
+ * @param runnable
+ * a {@code Runnable} whose method <code>run</code> will be
+ * executed by the new {@code Thread}
+ * @param threadName
+ * the name for the {@code Thread} being created
+ * @throws IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(ThreadGroup group, Runnable runnable, String threadName) {
+ if (threadName == null) {
+ throw new NullPointerException("threadName == null");
+ }
+
+ create(group, runnable, threadName, 0);
+ }
+
+ /**
+ * Constructs a new {@code Thread} with no {@code Runnable} object, the
+ * given name and belonging to the {@code ThreadGroup} passed as parameter.
+ *
+ * @param group
+ * {@code ThreadGroup} to which the new {@code Thread} will belong
+ * @param threadName
+ * the name for the {@code Thread} being created
+ * @throws IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(ThreadGroup group, String threadName) {
+ if (threadName == null) {
+ throw new NullPointerException("threadName == null");
+ }
+
+ create(group, null, threadName, 0);
+ }
+
+ /**
+ * Constructs a new {@code Thread} with a {@code Runnable} object, the given
+ * name and belonging to the {@code ThreadGroup} passed as parameter.
+ *
+ * @param group
+ * {@code ThreadGroup} to which the new {@code Thread} will
+ * belong
+ * @param runnable
+ * a {@code Runnable} whose method <code>run</code> will be
+ * executed by the new {@code Thread}
+ * @param threadName
+ * the name for the {@code Thread} being created
+ * @param stackSize
+ * a stack size for the new {@code Thread}. This has a highly
+ * platform-dependent interpretation. It may even be ignored
+ * completely.
+ * @throws IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
+ if (threadName == null) {
+ throw new NullPointerException("threadName == null");
+ }
+ create(group, runnable, threadName, stackSize);
+ }
+
+ /**
+ * Package-scope method invoked by Dalvik VM to create "internal"
+ * threads or attach threads created externally.
+ *
+ * Don't call Thread.currentThread(), since there may not be such
+ * a thing (e.g. for Main).
+ */
+ Thread(ThreadGroup group, String name, int priority, boolean daemon) {
+ synchronized (Thread.class) {
+ id = ++Thread.count;
+ }
+
+ if (name == null) {
+ this.name = "Thread-" + id;
+ } else {
+ this.name = name;
+ }
+
+ if (group == null) {
+ throw new InternalError("group == null");
+ }
+
+ this.group = group;
+
+ this.target = null;
+ this.stackSize = 0;
+ this.priority = priority;
+ this.daemon = daemon;
+
+ /* add ourselves to our ThreadGroup of choice */
+ this.group.addThread(this);
+ }
+
+ /**
+ * Initializes a new, existing Thread object with a runnable object,
+ * the given name and belonging to the ThreadGroup passed as parameter.
+ * This is the method that the several public constructors delegate their
+ * work to.
+ *
+ * @param group ThreadGroup to which the new Thread will belong
+ * @param runnable a java.lang.Runnable whose method <code>run</code> will
+ * be executed by the new Thread
+ * @param threadName Name for the Thread being created
+ * @param stackSize Platform dependent stack size
+ * @throws IllegalThreadStateException if <code>group.destroy()</code> has
+ * already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
+ Thread currentThread = Thread.currentThread();
+ if (group == null) {
+ group = currentThread.getThreadGroup();
+ }
+
+ if (group.isDestroyed()) {
+ throw new IllegalThreadStateException("Group already destroyed");
+ }
+
+ this.group = group;
+
+ synchronized (Thread.class) {
+ id = ++Thread.count;
+ }
+
+ if (threadName == null) {
+ this.name = "Thread-" + id;
+ } else {
+ this.name = threadName;
+ }
+
+ this.target = runnable;
+ this.stackSize = stackSize;
+
+ this.priority = currentThread.getPriority();
+
+ this.contextClassLoader = currentThread.contextClassLoader;
+
+ // Transfer over InheritableThreadLocals.
+ if (currentThread.inheritableValues != null) {
+ inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
+ }
+
+ // add ourselves to our ThreadGroup of choice
+ this.group.addThread(this);
+ }
+
+ /**
+ * Returns the number of active {@code Thread}s in the running {@code
+ * Thread}'s group and its subgroups.
+ *
+ * @return the number of {@code Thread}s
+ */
+ public static int activeCount() {
+ return currentThread().getThreadGroup().activeCount();
+ }
+
+ /**
+ * Does nothing.
+ */
+ public final void checkAccess() {
+ }
+
+ /**
+ * Returns the number of stack frames in this thread.
+ *
+ * @return Number of stack frames
+ * @deprecated The results of this call were never well defined. To make
+ * things worse, it would depend on whether the Thread was
+ * suspended or not, and suspend was deprecated too.
+ */
+ @Deprecated
+ public int countStackFrames() {
+ return getStackTrace().length;
+ }
+
+ /**
+ * Returns the Thread of the caller, that is, the current Thread.
+ */
+ public static native Thread currentThread();
+
+ /**
+ * Throws {@code UnsupportedOperationException}.
+ * @deprecated Not implemented.
+ */
+ @Deprecated
+ public void destroy() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Prints to the standard error stream a text representation of the current
+ * stack for this Thread.
+ *
+ * @see Throwable#printStackTrace()
+ */
+ public static void dumpStack() {
+ new Throwable("stack dump").printStackTrace();
+ }
+
+ /**
+ * Copies an array with all Threads which are in the same ThreadGroup as the
+ * receiver - and subgroups - into the array <code>threads</code> passed as
+ * parameter. If the array passed as parameter is too small no exception is
+ * thrown - the extra elements are simply not copied.
+ *
+ * @param threads
+ * array into which the Threads will be copied
+ * @return How many Threads were copied over
+ */
+ public static int enumerate(Thread[] threads) {
+ Thread thread = Thread.currentThread();
+ return thread.getThreadGroup().enumerate(threads);
+ }
+
+ /**
+ * Returns a map of all the currently live threads to their stack traces.
+ */
+ public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
+ Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>();
+
+ // Find out how many live threads we have. Allocate a bit more
+ // space than needed, in case new ones are just being created.
+ int count = ThreadGroup.systemThreadGroup.activeCount();
+ Thread[] threads = new Thread[count + count / 2];
+
+ // Enumerate the threads and collect the stacktraces.
+ count = ThreadGroup.systemThreadGroup.enumerate(threads);
+ for (int i = 0; i < count; i++) {
+ map.put(threads[i], threads[i].getStackTrace());
+ }
+
+ return map;
+ }
+
+ /**
+ * Returns the context ClassLoader for this Thread.
+ *
+ * @return ClassLoader The context ClassLoader
+ * @see java.lang.ClassLoader
+ * @see #getContextClassLoader()
+ */
+ public ClassLoader getContextClassLoader() {
+ return contextClassLoader;
+ }
+
+ /**
+ * Returns the default exception handler that's executed when uncaught
+ * exception terminates a thread.
+ *
+ * @return an {@link UncaughtExceptionHandler} or <code>null</code> if
+ * none exists.
+ */
+ public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
+ return defaultUncaughtHandler;
+ }
+
+ /**
+ * Returns the thread's identifier. The ID is a positive <code>long</code>
+ * generated on thread creation, is unique to the thread, and doesn't change
+ * during the lifetime of the thread; the ID may be reused after the thread
+ * has been terminated.
+ *
+ * @return the thread's ID.
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * Returns the name of the Thread.
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the priority of the Thread.
+ */
+ public final int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Returns an array of {@link StackTraceElement} representing the current thread's stack.
+ */
+ public StackTraceElement[] getStackTrace() {
+ StackTraceElement ste[] = VMStack.getThreadStackTrace(this);
+ return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT;
+ }
+
+ /**
+ * Returns the current state of the Thread. This method is useful for
+ * monitoring purposes.
+ *
+ * @return a {@link State} value.
+ */
+ public State getState() {
+ return State.values()[nativeGetStatus(hasBeenStarted)];
+ }
+
+ private native int nativeGetStatus(boolean hasBeenStarted);
+
+ /**
+ * Returns the ThreadGroup to which this Thread belongs.
+ *
+ * @return the Thread's ThreadGroup
+ */
+ public final ThreadGroup getThreadGroup() {
+ // TODO This should actually be done at native termination.
+ if (getState() == Thread.State.TERMINATED) {
+ return null;
+ } else {
+ return group;
+ }
+ }
+
+ /**
+ * Returns the thread's uncaught exception handler. If not explicitly set,
+ * then the ThreadGroup's handler is returned. If the thread is terminated,
+ * then <code>null</code> is returned.
+ *
+ * @return an {@link UncaughtExceptionHandler} instance or {@code null}.
+ */
+ public UncaughtExceptionHandler getUncaughtExceptionHandler() {
+ if (uncaughtHandler != null) {
+ return uncaughtHandler;
+ } else {
+ return group; // ThreadGroup is instance of UEH
+ }
+ }
+
+ /**
+ * Posts an interrupt request to this {@code Thread}. The behavior depends on
+ * the state of this {@code Thread}:
+ * <ul>
+ * <li>
+ * {@code Thread}s blocked in one of {@code Object}'s {@code wait()} methods
+ * or one of {@code Thread}'s {@code join()} or {@code sleep()} methods will
+ * be woken up, their interrupt status will be cleared, and they receive an
+ * {@link InterruptedException}.
+ * <li>
+ * {@code Thread}s blocked in an I/O operation of an
+ * {@link java.nio.channels.InterruptibleChannel} will have their interrupt
+ * status set and receive an
+ * {@link java.nio.channels.ClosedByInterruptException}. Also, the channel
+ * will be closed.
+ * <li>
+ * {@code Thread}s blocked in a {@link java.nio.channels.Selector} will have
+ * their interrupt status set and return immediately. They don't receive an
+ * exception in this case.
+ * <ul>
+ *
+ * @see Thread#interrupted
+ * @see Thread#isInterrupted
+ */
+ public void interrupt() {
+ // Interrupt this thread before running actions so that other
+ // threads that observe the interrupt as a result of an action
+ // will see that this thread is in the interrupted state.
+ nativeInterrupt();
+
+ synchronized (interruptActions) {
+ for (int i = interruptActions.size() - 1; i >= 0; i--) {
+ interruptActions.get(i).run();
+ }
+ }
+ }
+
+ private native void nativeInterrupt();
+
+ /**
+ * Returns a <code>boolean</code> indicating whether the current Thread (
+ * <code>currentThread()</code>) has a pending interrupt request (<code>
+ * true</code>) or not (<code>false</code>). It also has the side-effect of
+ * clearing the flag.
+ *
+ * @return a <code>boolean</code> indicating the interrupt status
+ * @see Thread#currentThread
+ * @see Thread#interrupt
+ * @see Thread#isInterrupted
+ */
+ public static native boolean interrupted();
+
+ /**
+ * Returns <code>true</code> if the receiver has already been started and
+ * still runs code (hasn't died yet). Returns <code>false</code> either if
+ * the receiver hasn't been started yet or if it has already started and run
+ * to completion and died.
+ *
+ * @return a <code>boolean</code> indicating the liveness of the Thread
+ * @see Thread#start
+ */
+ public final boolean isAlive() {
+ return (nativePeer != 0);
+ }
+
+ /**
+ * Tests whether this is a daemon thread.
+ * A daemon thread only runs as long as there are non-daemon threads running.
+ * When the last non-daemon thread ends, the runtime will exit. This is not
+ * normally relevant to applications with a UI.
+ */
+ public final boolean isDaemon() {
+ return daemon;
+ }
+
+ /**
+ * Returns a <code>boolean</code> indicating whether the receiver has a
+ * pending interrupt request (<code>true</code>) or not (
+ * <code>false</code>)
+ *
+ * @return a <code>boolean</code> indicating the interrupt status
+ * @see Thread#interrupt
+ * @see Thread#interrupted
+ */
+ public native boolean isInterrupted();
+
+ /**
+ * Blocks the current Thread (<code>Thread.currentThread()</code>) until
+ * the receiver finishes its execution and dies.
+ *
+ * @throws InterruptedException if <code>interrupt()</code> was called for
+ * the receiver while it was in the <code>join()</code> call
+ * @see Object#notifyAll
+ * @see java.lang.ThreadDeath
+ */
+ public final void join() throws InterruptedException {
+ synchronized (lock) {
+ while (isAlive()) {
+ lock.wait();
+ }
+ }
+ }
+
+ /**
+ * Blocks the current Thread (<code>Thread.currentThread()</code>) until
+ * the receiver finishes its execution and dies or the specified timeout
+ * expires, whatever happens first.
+ *
+ * @param millis The maximum time to wait (in milliseconds).
+ * @throws InterruptedException if <code>interrupt()</code> was called for
+ * the receiver while it was in the <code>join()</code> call
+ * @see Object#notifyAll
+ * @see java.lang.ThreadDeath
+ */
+ public final void join(long millis) throws InterruptedException {
+ join(millis, 0);
+ }
+
+ /**
+ * Blocks the current Thread (<code>Thread.currentThread()</code>) until
+ * the receiver finishes its execution and dies or the specified timeout
+ * expires, whatever happens first.
+ *
+ * @param millis The maximum time to wait (in milliseconds).
+ * @param nanos Extra nanosecond precision
+ * @throws InterruptedException if <code>interrupt()</code> was called for
+ * the receiver while it was in the <code>join()</code> call
+ * @see Object#notifyAll
+ * @see java.lang.ThreadDeath
+ */
+ public final void join(long millis, int nanos) throws InterruptedException {
+ if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) {
+ throw new IllegalArgumentException("bad timeout: millis=" + millis + ",nanos=" + nanos);
+ }
+
+ // avoid overflow: if total > 292,277 years, just wait forever
+ boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI;
+ boolean forever = (millis | nanos) == 0;
+ if (forever | overflow) {
+ join();
+ return;
+ }
+
+ synchronized (lock) {
+ if (!isAlive()) {
+ return;
+ }
+
+ // guaranteed not to overflow
+ long nanosToWait = millis * NANOS_PER_MILLI + nanos;
+
+ // wait until this thread completes or the timeout has elapsed
+ long start = System.nanoTime();
+ while (true) {
+ lock.wait(millis, nanos);
+ if (!isAlive()) {
+ break;
+ }
+ long nanosElapsed = System.nanoTime() - start;
+ long nanosRemaining = nanosToWait - nanosElapsed;
+ if (nanosRemaining <= 0) {
+ break;
+ }
+ millis = nanosRemaining / NANOS_PER_MILLI;
+ nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI);
+ }
+ }
+ }
+
+ /**
+ * Throws {@code UnsupportedOperationException}.
+ * @deprecated Only useful in conjunction with deprecated method {@link Thread#suspend}.
+ */
+ @Deprecated
+ public final void resume() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Calls the <code>run()</code> method of the Runnable object the receiver
+ * holds. If no Runnable is set, does nothing.
+ *
+ * @see Thread#start
+ */
+ public void run() {
+ if (target != null) {
+ target.run();
+ }
+ }
+
+ /**
+ * Set the context ClassLoader for the receiver.
+ *
+ * @param cl The context ClassLoader
+ * @see #getContextClassLoader()
+ */
+ public void setContextClassLoader(ClassLoader cl) {
+ contextClassLoader = cl;
+ }
+
+ /**
+ * Marks this thread as a daemon thread.
+ * A daemon thread only runs as long as there are non-daemon threads running.
+ * When the last non-daemon thread ends, the runtime will exit. This is not
+ * normally relevant to applications with a UI.
+ * @throws IllegalThreadStateException - if this thread has already started.
+ */
+ public final void setDaemon(boolean isDaemon) {
+ checkNotStarted();
+
+ if (nativePeer == 0) {
+ daemon = isDaemon;
+ }
+ }
+
+ private void checkNotStarted() {
+ if (hasBeenStarted) {
+ throw new IllegalThreadStateException("Thread already started");
+ }
+ }
+
+ /**
+ * Sets the default uncaught exception handler. This handler is invoked in
+ * case any Thread dies due to an unhandled exception.
+ *
+ * @param handler
+ * The handler to set or null.
+ */
+ public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
+ Thread.defaultUncaughtHandler = handler;
+ }
+
+ /**
+ * Adds a runnable to be invoked upon interruption. If this thread has
+ * already been interrupted, the runnable will be invoked immediately. The
+ * action should be idempotent as it may be invoked multiple times for a
+ * single interruption.
+ *
+ * <p>Each call to this method must be matched with a corresponding call to
+ * {@link #popInterruptAction$}.
+ *
+ * @hide used by NIO
+ */
+ public final void pushInterruptAction$(Runnable interruptAction) {
+ synchronized (interruptActions) {
+ interruptActions.add(interruptAction);
+ }
+
+ if (interruptAction != null && isInterrupted()) {
+ interruptAction.run();
+ }
+ }
+
+ /**
+ * Removes {@code interruptAction} so it is not invoked upon interruption.
+ *
+ * @param interruptAction the pushed action, used to check that the call
+ * stack is correctly nested.
+ *
+ * @hide used by NIO
+ */
+ public final void popInterruptAction$(Runnable interruptAction) {
+ synchronized (interruptActions) {
+ Runnable removed = interruptActions.remove(interruptActions.size() - 1);
+ if (interruptAction != removed) {
+ throw new IllegalArgumentException("Expected " + interruptAction + " but was " + removed);
+ }
+ }
+ }
+
+ /**
+ * Sets the name of the Thread.
+ *
+ * @param threadName the new name for the Thread
+ * @see Thread#getName
+ */
+ public final void setName(String threadName) {
+ if (threadName == null) {
+ throw new NullPointerException("threadName == null");
+ }
+ // The lock is taken to ensure no race occurs between starting the
+ // the thread and setting its name (and the name of its native peer).
+ synchronized (this) {
+ this.name = threadName;
+
+ if (isAlive()) {
+ nativeSetName(threadName);
+ }
+ }
+ }
+
+ /**
+ * Tell the VM that the thread's name has changed. This is useful for
+ * DDMS, which would otherwise be oblivious to Thread.setName calls.
+ */
+ private native void nativeSetName(String newName);
+
+ /**
+ * Sets the priority of this thread. If the requested priority is greater than the
+ * parent thread group's {@link java.lang.ThreadGroup#getMaxPriority}, the group's maximum
+ * priority will be used instead.
+ *
+ * @throws IllegalArgumentException - if the new priority is greater than {@link #MAX_PRIORITY}
+ * or less than {@link #MIN_PRIORITY}
+ */
+ public final void setPriority(int priority) {
+ if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
+ throw new IllegalArgumentException("Priority out of range: " + priority);
+ }
+
+ if (priority > group.getMaxPriority()) {
+ priority = group.getMaxPriority();
+ }
+
+ // The lock is taken to ensure no race occurs between starting the
+ // the thread and setting its priority (and the priority of its native peer).
+ synchronized (this) {
+ this.priority = priority;
+
+ if (isAlive()) {
+ nativeSetPriority(priority);
+ }
+ }
+ }
+
+ private native void nativeSetPriority(int newPriority);
+
+ /**
+ * <p>
+ * Sets the uncaught exception handler. This handler is invoked in case this
+ * Thread dies due to an unhandled exception.
+ * </p>
+ *
+ * @param handler
+ * The handler to set or <code>null</code>.
+ */
+ public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
+ uncaughtHandler = handler;
+ }
+
+ /**
+ * Causes the thread which sent this message to sleep for the given interval
+ * of time (given in milliseconds). The precision is not guaranteed - the
+ * Thread may sleep more or less than requested.
+ *
+ * @param time
+ * The time to sleep in milliseconds.
+ * @throws InterruptedException
+ * if <code>interrupt()</code> was called for this Thread while
+ * it was sleeping
+ * @see Thread#interrupt()
+ */
+ public static void sleep(long time) throws InterruptedException {
+ Thread.sleep(time, 0);
+ }
+
+ /**
+ * Causes the thread which sent this message to sleep for the given interval
+ * of time (given in milliseconds and nanoseconds). The precision is not
+ * guaranteed - the Thread may sleep more or less than requested.
+ *
+ * @param millis
+ * The time to sleep in milliseconds.
+ * @param nanos
+ * Extra nanosecond precision
+ * @throws InterruptedException
+ * if <code>interrupt()</code> was called for this Thread while
+ * it was sleeping
+ * @see Thread#interrupt()
+ */
+ public static void sleep(long millis, int nanos) throws InterruptedException {
+ // The JLS 3rd edition, section 17.9 says: "...sleep for zero
+ // time...need not have observable effects."
+ if (millis == 0 && nanos == 0) {
+ return;
+ }
+
+ long start = System.nanoTime();
+ long duration = (millis * NANOS_PER_MILLI) + nanos;
+
+ Object lock = currentThread().lock;
+
+ // Wait may return early, so loop until sleep duration passes.
+ synchronized (lock) {
+ while (true) {
+ sleep(lock, millis, nanos);
+
+ long now = System.nanoTime();
+ long elapsed = now - start;
+
+ if (elapsed >= duration) {
+ break;
+ }
+
+ duration -= elapsed;
+ start = now;
+ millis = duration / NANOS_PER_MILLI;
+ nanos = (int) (duration % NANOS_PER_MILLI);
+ }
+ }
+ }
+
+ private static native void sleep(Object lock, long millis, int nanos);
+
+ /**
+ * Starts the new Thread of execution. The <code>run()</code> method of
+ * the receiver will be called by the receiver Thread itself (and not the
+ * Thread calling <code>start()</code>).
+ *
+ * @throws IllegalThreadStateException - if this thread has already started.
+ * @see Thread#run
+ */
+ public synchronized void start() {
+ checkNotStarted();
+
+ hasBeenStarted = true;
+
+ nativeCreate(this, stackSize, daemon);
+ }
+
+ private native static void nativeCreate(Thread t, long stackSize, boolean daemon);
+
+ /**
+ * Requests the receiver Thread to stop and throw ThreadDeath. The Thread is
+ * resumed if it was suspended and awakened if it was sleeping, so that it
+ * can proceed to throw ThreadDeath.
+ *
+ * @deprecated because stopping a thread in this manner is unsafe and can
+ * leave your application and the VM in an unpredictable state.
+ */
+ @Deprecated
+ public final void stop() {
+ stop(new ThreadDeath());
+ }
+
+ /**
+ * Throws {@code UnsupportedOperationException}.
+ * @deprecated because stopping a thread in this manner is unsafe and can
+ * leave your application and the VM in an unpredictable state.
+ */
+ @Deprecated
+ public final synchronized void stop(Throwable throwable) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Throws {@code UnsupportedOperationException}.
+ * @deprecated May cause deadlocks.
+ */
+ @Deprecated
+ public final void suspend() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a string containing a concise, human-readable description of the
+ * Thread. It includes the Thread's name, priority, and group name.
+ *
+ * @return a printable representation for the receiver.
+ */
+ @Override
+ public String toString() {
+ return "Thread[" + name + "," + priority + "," + group.getName() + "]";
+ }
+
+ /**
+ * Causes the calling Thread to yield execution time to another Thread that
+ * is ready to run. The actual scheduling is implementation-dependent.
+ */
+ public static native void yield();
+
+ /**
+ * Indicates whether the current Thread has a monitor lock on the specified
+ * object.
+ *
+ * @param object the object to test for the monitor lock
+ * @return true if the current thread has a monitor lock on the specified
+ * object; false otherwise
+ */
+ public static boolean holdsLock(Object object) {
+ return currentThread().nativeHoldsLock(object);
+ }
+
+ private native boolean nativeHoldsLock(Object object);
+
+ /**
+ * Implemented by objects that want to handle cases where a thread is being
+ * terminated by an uncaught exception. Upon such termination, the handler
+ * is notified of the terminating thread and causal exception. If there is
+ * no explicit handler set then the thread's group is the default handler.
+ */
+ public static interface UncaughtExceptionHandler {
+ /**
+ * The thread is being terminated by an uncaught exception. Further
+ * exceptions thrown in this method are prevent the remainder of the
+ * method from executing, but are otherwise ignored.
+ *
+ * @param thread the thread that has an uncaught exception
+ * @param ex the exception that was thrown
+ */
+ void uncaughtException(Thread thread, Throwable ex);
+ }
+
+ /**
+ * Unparks this thread. This unblocks the thread it if it was
+ * previously parked, or indicates that the thread is "preemptively
+ * unparked" if it wasn't already parked. The latter means that the
+ * next time the thread is told to park, it will merely clear its
+ * latent park bit and carry on without blocking.
+ *
+ * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+ * in-depth information of the behavior of this method.</p>
+ *
+ * @hide for Unsafe
+ */
+ public void unpark() {
+ synchronized (lock) {
+ switch (parkState) {
+ case ParkState.PREEMPTIVELY_UNPARKED: {
+ /*
+ * Nothing to do in this case: By definition, a
+ * preemptively unparked thread is to remain in
+ * the preemptively unparked state if it is told
+ * to unpark.
+ */
+ break;
+ }
+ case ParkState.UNPARKED: {
+ parkState = ParkState.PREEMPTIVELY_UNPARKED;
+ break;
+ }
+ default /*parked*/: {
+ parkState = ParkState.UNPARKED;
+ lock.notifyAll();
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Parks the current thread for a particular number of nanoseconds, or
+ * indefinitely. If not indefinitely, this method unparks the thread
+ * after the given number of nanoseconds if no other thread unparks it
+ * first. If the thread has been "preemptively unparked," this method
+ * cancels that unparking and returns immediately. This method may
+ * also return spuriously (that is, without the thread being told to
+ * unpark and without the indicated amount of time elapsing).
+ *
+ * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+ * in-depth information of the behavior of this method.</p>
+ *
+ * <p>This method must only be called when <code>this</code> is the current
+ * thread.
+ *
+ * @param nanos number of nanoseconds to park for or <code>0</code>
+ * to park indefinitely
+ * @throws IllegalArgumentException thrown if <code>nanos < 0</code>
+ *
+ * @hide for Unsafe
+ */
+ public void parkFor(long nanos) {
+ synchronized (lock) {
+ switch (parkState) {
+ case ParkState.PREEMPTIVELY_UNPARKED: {
+ parkState = ParkState.UNPARKED;
+ break;
+ }
+ case ParkState.UNPARKED: {
+ long millis = nanos / NANOS_PER_MILLI;
+ nanos %= NANOS_PER_MILLI;
+
+ parkState = ParkState.PARKED;
+ try {
+ lock.wait(millis, (int) nanos);
+ } catch (InterruptedException ex) {
+ interrupt();
+ } finally {
+ /*
+ * Note: If parkState manages to become
+ * PREEMPTIVELY_UNPARKED before hitting this
+ * code, it should left in that state.
+ */
+ if (parkState == ParkState.PARKED) {
+ parkState = ParkState.UNPARKED;
+ }
+ }
+ break;
+ }
+ default /*parked*/: {
+ throw new AssertionError("Attempt to repark");
+ }
+ }
+ }
+ }
+
+ /**
+ * Parks the current thread until the specified system time. This
+ * method attempts to unpark the current thread immediately after
+ * <code>System.currentTimeMillis()</code> reaches the specified
+ * value, if no other thread unparks it first. If the thread has
+ * been "preemptively unparked," this method cancels that
+ * unparking and returns immediately. This method may also return
+ * spuriously (that is, without the thread being told to unpark
+ * and without the indicated amount of time elapsing).
+ *
+ * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+ * in-depth information of the behavior of this method.</p>
+ *
+ * <p>This method must only be called when <code>this</code> is the
+ * current thread.
+ *
+ * @param time the time after which the thread should be unparked,
+ * in absolute milliseconds-since-the-epoch
+ *
+ * @hide for Unsafe
+ */
+ public void parkUntil(long time) {
+ synchronized (lock) {
+ /*
+ * Note: This conflates the two time bases of "wall clock"
+ * time and "monotonic uptime" time. However, given that
+ * the underlying system can only wait on monotonic time,
+ * it is unclear if there is any way to avoid the
+ * conflation. The downside here is that if, having
+ * calculated the delay, the wall clock gets moved ahead,
+ * this method may not return until well after the wall
+ * clock has reached the originally designated time. The
+ * reverse problem (the wall clock being turned back)
+ * isn't a big deal, since this method is allowed to
+ * spuriously return for any reason, and this situation
+ * can safely be construed as just such a spurious return.
+ */
+ long delayMillis = time - System.currentTimeMillis();
+
+ if (delayMillis <= 0) {
+ parkState = ParkState.UNPARKED;
+ } else {
+ parkFor(delayMillis * NANOS_PER_MILLI);
+ }
+ }
+ }
+}
diff --git a/libart/src/main/java/java/lang/ThreadGroup.java b/libart/src/main/java/java/lang/ThreadGroup.java
new file mode 100644
index 0000000..51b2137
--- /dev/null
+++ b/libart/src/main/java/java/lang/ThreadGroup.java
@@ -0,0 +1,726 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 java.lang;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import libcore.util.CollectionUtils;
+
+/**
+ * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
+ * This class is obsolete. See <i>Effective Java</i> Item 73, "Avoid thread groups" for details.
+ * @see Thread
+ */
+public class ThreadGroup implements Thread.UncaughtExceptionHandler {
+
+ // Name of this ThreadGroup
+ // VM needs this field name for debugging.
+ private String name;
+
+ // Maximum priority for Threads inside this ThreadGroup
+ private int maxPriority = Thread.MAX_PRIORITY;
+
+ // The ThreadGroup to which this ThreadGroup belongs
+ // VM needs this field name for debugging.
+ final ThreadGroup parent;
+
+ /**
+ * Weak references to the threads in this group.
+ * Access is guarded by synchronizing on this field.
+ */
+ private final List<WeakReference<Thread>> threadRefs = new ArrayList<WeakReference<Thread>>(5);
+
+ /**
+ * View of the threads.
+ * Access is guarded by synchronizing on threadRefs.
+ */
+ private final Iterable<Thread> threads = CollectionUtils.dereferenceIterable(threadRefs, true);
+
+ /**
+ * Thread groups. Access is guarded by synchronizing on this field.
+ */
+ private final List<ThreadGroup> groups = new ArrayList<ThreadGroup>(3);
+
+ // Whether this ThreadGroup is a daemon ThreadGroup or not
+ private boolean isDaemon;
+
+ // Whether this ThreadGroup has already been destroyed or not
+ private boolean isDestroyed;
+
+ /* the VM uses these directly; do not rename */
+ static final ThreadGroup systemThreadGroup = new ThreadGroup();
+ static final ThreadGroup mainThreadGroup = new ThreadGroup(systemThreadGroup, "main");
+
+ /**
+ * Constructs a new {@code ThreadGroup} with the given name. The new {@code ThreadGroup}
+ * will be child of the {@code ThreadGroup} to which the calling thread belongs.
+ *
+ * @param name the name
+ * @see Thread#currentThread
+ */
+ public ThreadGroup(String name) {
+ this(Thread.currentThread().getThreadGroup(), name);
+ }
+
+ /**
+ * Constructs a new {@code ThreadGroup} with the given name, as a child of the
+ * given {@code ThreadGroup}.
+ *
+ * @param parent the parent
+ * @param name the name
+ * @throws NullPointerException if {@code parent == null}
+ * @throws IllegalThreadStateException if {@code parent} has been
+ * destroyed already
+ */
+ public ThreadGroup(ThreadGroup parent, String name) {
+ if (parent == null) {
+ throw new NullPointerException("parent == null");
+ }
+ this.name = name;
+ this.parent = parent;
+ if (parent != null) {
+ parent.add(this);
+ this.setMaxPriority(parent.getMaxPriority());
+ if (parent.isDaemon()) {
+ this.setDaemon(true);
+ }
+ }
+ }
+
+ /**
+ * Initialize the special "system" ThreadGroup. Was "main" in Harmony,
+ * but we have an additional group above that in Android.
+ */
+ private ThreadGroup() {
+ this.name = "system";
+ this.parent = null;
+ }
+
+ /**
+ * Returns the number of running {@code Thread}s which are children of this thread group,
+ * directly or indirectly.
+ *
+ * @return the number of children
+ */
+ public int activeCount() {
+ int count = 0;
+ synchronized (threadRefs) {
+ for (Thread thread : threads) {
+ if (thread.isAlive()) {
+ count++;
+ }
+ }
+ }
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ count += group.activeCount();
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Returns the number of {@code ThreadGroup}s which are children of this group,
+ * directly or indirectly.
+ *
+ * @return the number of children
+ */
+ public int activeGroupCount() {
+ int count = 0;
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ // One for this group & the subgroups
+ count += 1 + group.activeGroupCount();
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Adds a {@code ThreadGroup} to this thread group.
+ *
+ * @param g ThreadGroup to add
+ * @throws IllegalThreadStateException if this group has been destroyed already
+ */
+ private void add(ThreadGroup g) throws IllegalThreadStateException {
+ synchronized (groups) {
+ if (isDestroyed) {
+ throw new IllegalThreadStateException();
+ }
+ groups.add(g);
+ }
+ }
+
+ /**
+ * Does nothing. The definition of this method depends on the deprecated
+ * method {@link #suspend()}. The exact behavior of this call was never
+ * specified.
+ *
+ * @param b Used to control low memory implicit suspension
+ * @return {@code true} (always)
+ *
+ * @deprecated Required deprecated method suspend().
+ */
+ @Deprecated
+ public boolean allowThreadSuspension(boolean b) {
+ // Does not apply to this VM, no-op
+ return true;
+ }
+
+ /**
+ * Does nothing.
+ */
+ public final void checkAccess() {
+ }
+
+ /**
+ * Destroys this thread group and recursively all its subgroups. It is only legal
+ * to destroy a {@code ThreadGroup} that has no threads in it. Any daemon
+ * {@code ThreadGroup} is destroyed automatically when it becomes empty (no threads
+ * or thread groups in it).
+ *
+ * @throws IllegalThreadStateException if this thread group or any of its
+ * subgroups has been destroyed already or if it still contains
+ * threads.
+ */
+ public final void destroy() {
+ synchronized (threadRefs) {
+ synchronized (groups) {
+ if (isDestroyed) {
+ throw new IllegalThreadStateException(
+ "Thread group was already destroyed: "
+ + (this.name != null ? this.name : "n/a"));
+ }
+ if (threads.iterator().hasNext()) {
+ throw new IllegalThreadStateException(
+ "Thread group still contains threads: "
+ + (this.name != null ? this.name : "n/a"));
+ }
+ // Call recursively for subgroups
+ while (!groups.isEmpty()) {
+ // We always get the first element - remember, when the
+ // child dies it removes itself from our collection. See
+ // below.
+ groups.get(0).destroy();
+ }
+
+ if (parent != null) {
+ parent.remove(this);
+ }
+
+ // Now that the ThreadGroup is really destroyed it can be tagged as so
+ this.isDestroyed = true;
+ }
+ }
+ }
+
+ /*
+ * Auxiliary method that destroys this thread group and recursively all its
+ * subgroups if this is a daemon ThreadGroup.
+ *
+ * @see #destroy
+ * @see #setDaemon
+ * @see #isDaemon
+ */
+ private void destroyIfEmptyDaemon() {
+ // Has to be non-destroyed daemon to make sense
+ synchronized (threadRefs) {
+ if (isDaemon && !isDestroyed && !threads.iterator().hasNext()) {
+ synchronized (groups) {
+ if (groups.isEmpty()) {
+ destroy();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Iterates over all active threads in this group (and its sub-groups) and
+ * stores the threads in the given array. Returns when the array is full or
+ * no more threads remain, whichever happens first.
+ *
+ * <p>Note that this method will silently ignore any threads that don't fit in the
+ * supplied array.
+ *
+ * @param threads the array into which the {@code Thread}s will be copied
+ * @return the number of {@code Thread}s that were copied
+ */
+ public int enumerate(Thread[] threads) {
+ return enumerate(threads, true);
+ }
+
+ /**
+ * Iterates over all active threads in this group (and, optionally, its
+ * sub-groups) and stores the threads in the given array. Returns when the
+ * array is full or no more threads remain, whichever happens first.
+ *
+ * <p>Note that this method will silently ignore any threads that don't fit in the
+ * supplied array.
+ *
+ * @param threads the array into which the {@code Thread}s will be copied
+ * @param recurse indicates whether {@code Thread}s in subgroups should be
+ * recursively copied as well
+ * @return the number of {@code Thread}s that were copied
+ */
+ public int enumerate(Thread[] threads, boolean recurse) {
+ return enumerateGeneric(threads, recurse, 0, true);
+ }
+
+ /**
+ * Iterates over all thread groups in this group (and its sub-groups) and
+ * and stores the groups in the given array. Returns when the array is full
+ * or no more groups remain, whichever happens first.
+ *
+ * <p>Note that this method will silently ignore any thread groups that don't fit in the
+ * supplied array.
+ *
+ * @param groups the array into which the {@code ThreadGroup}s will be copied
+ * @return the number of {@code ThreadGroup}s that were copied
+ */
+ public int enumerate(ThreadGroup[] groups) {
+ return enumerate(groups, true);
+ }
+
+ /**
+ * Iterates over all thread groups in this group (and, optionally, its
+ * sub-groups) and stores the groups in the given array. Returns when
+ * the array is full or no more groups remain, whichever happens first.
+ *
+ * <p>Note that this method will silently ignore any thread groups that don't fit in the
+ * supplied array.
+ *
+ * @param groups the array into which the {@code ThreadGroup}s will be copied
+ * @param recurse indicates whether {@code ThreadGroup}s in subgroups should be
+ * recursively copied as well or not
+ * @return the number of {@code ThreadGroup}s that were copied
+ */
+ public int enumerate(ThreadGroup[] groups, boolean recurse) {
+ return enumerateGeneric(groups, recurse, 0, false);
+ }
+
+ /**
+ * Copies into <param>enumeration</param> starting at
+ * <param>enumerationIndex</param> all Threads or ThreadGroups in the
+ * receiver. If <param>recurse</param> is true, recursively enumerate the
+ * elements in subgroups.
+ *
+ * If the array passed as parameter is too small no exception is thrown -
+ * the extra elements are simply not copied.
+ *
+ * @param enumeration array into which the elements will be copied
+ * @param recurse Indicates whether subgroups should be enumerated or not
+ * @param enumerationIndex Indicates in which position of the enumeration
+ * array we are
+ * @param enumeratingThreads Indicates whether we are enumerating Threads or
+ * ThreadGroups
+ * @return How many elements were enumerated/copied over
+ */
+ private int enumerateGeneric(Object[] enumeration, boolean recurse, int enumerationIndex,
+ boolean enumeratingThreads) {
+ if (enumeratingThreads) {
+ synchronized (threadRefs) {
+ // walk the references directly so we can iterate in reverse order
+ for (int i = threadRefs.size() - 1; i >= 0; --i) {
+ Thread thread = threadRefs.get(i).get();
+ if (thread != null && thread.isAlive()) {
+ if (enumerationIndex >= enumeration.length) {
+ return enumerationIndex;
+ }
+ enumeration[enumerationIndex++] = thread;
+ }
+ }
+ }
+ } else {
+ synchronized (groups) {
+ for (int i = groups.size() - 1; i >= 0; --i) {
+ if (enumerationIndex >= enumeration.length) {
+ return enumerationIndex;
+ }
+ enumeration[enumerationIndex++] = groups.get(i);
+ }
+ }
+ }
+
+ if (recurse) {
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ if (enumerationIndex >= enumeration.length) {
+ return enumerationIndex;
+ }
+ enumerationIndex = group.enumerateGeneric(enumeration, recurse,
+ enumerationIndex, enumeratingThreads);
+ }
+ }
+ }
+ return enumerationIndex;
+ }
+
+ /**
+ * Returns the maximum allowed priority for a {@code Thread} in this thread group.
+ *
+ * @return the maximum priority
+ *
+ * @see #setMaxPriority
+ */
+ public final int getMaxPriority() {
+ return maxPriority;
+ }
+
+ /**
+ * Returns the name of this thread group.
+ *
+ * @return the group's name
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Returns this thread group's parent {@code ThreadGroup}. It can be null if this
+ * is the the root ThreadGroup.
+ *
+ * @return the parent
+ */
+ public final ThreadGroup getParent() {
+ return parent;
+ }
+
+ /**
+ * Interrupts every {@code Thread} in this group and recursively in all its
+ * subgroups.
+ *
+ * @see Thread#interrupt
+ */
+ public final void interrupt() {
+ synchronized (threadRefs) {
+ for (Thread thread : threads) {
+ thread.interrupt();
+ }
+ }
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ group.interrupt();
+ }
+ }
+ }
+
+ /**
+ * Checks whether this thread group is a daemon {@code ThreadGroup}.
+ *
+ * @return true if this thread group is a daemon {@code ThreadGroup}
+ *
+ * @see #setDaemon
+ * @see #destroy
+ */
+ public final boolean isDaemon() {
+ return isDaemon;
+ }
+
+ /**
+ * Checks whether this thread group has already been destroyed.
+ *
+ * @return true if this thread group has already been destroyed
+ * @see #destroy
+ */
+ public synchronized boolean isDestroyed() {
+ return isDestroyed;
+ }
+
+ /**
+ * Outputs to {@code System.out} a text representation of the
+ * hierarchy of {@code Thread}s and {@code ThreadGroup}s in this thread group (and recursively).
+ * Proper indentation is used to show the nesting of groups inside groups
+ * and threads inside groups.
+ */
+ public void list() {
+ // We start in a fresh line
+ System.out.println();
+ list(0);
+ }
+
+ /*
+ * Outputs to {@code System.out}a text representation of the
+ * hierarchy of Threads and ThreadGroups in this thread group (and recursively).
+ * The indentation will be four spaces per level of nesting.
+ *
+ * @param levels How many levels of nesting, so that proper indentation can
+ * be output.
+ */
+ private void list(int levels) {
+ indent(levels);
+ System.out.println(this.toString());
+
+ ++levels;
+ synchronized (threadRefs) {
+ for (Thread thread : threads) {
+ indent(levels);
+ System.out.println(thread);
+ }
+ }
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ group.list(levels);
+ }
+ }
+ }
+
+ private void indent(int levels) {
+ for (int i = 0; i < levels; i++) {
+ System.out.print(" "); // 4 spaces for each level
+ }
+ }
+
+ /**
+ * Checks whether this thread group is a direct or indirect parent group of a
+ * given {@code ThreadGroup}.
+ *
+ * @param g the potential child {@code ThreadGroup}
+ * @return true if this thread group is parent of {@code g}
+ */
+ public final boolean parentOf(ThreadGroup g) {
+ while (g != null) {
+ if (this == g) {
+ return true;
+ }
+ g = g.parent;
+ }
+ return false;
+ }
+
+ /**
+ * Removes an immediate subgroup.
+ *
+ * @param g ThreadGroup to remove
+ *
+ * @see #add(Thread)
+ * @see #add(ThreadGroup)
+ */
+ private void remove(ThreadGroup g) {
+ synchronized (groups) {
+ for (Iterator<ThreadGroup> i = groups.iterator(); i.hasNext(); ) {
+ ThreadGroup threadGroup = i.next();
+ if (threadGroup.equals(g)) {
+ i.remove();
+ break;
+ }
+ }
+ }
+ destroyIfEmptyDaemon();
+ }
+
+ /**
+ * Resumes every thread in this group and recursively in all its
+ * subgroups.
+ *
+ * @see Thread#resume
+ * @see #suspend
+ *
+ * @deprecated Requires deprecated method Thread.resume().
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public final void resume() {
+ synchronized (threadRefs) {
+ for (Thread thread : threads) {
+ thread.resume();
+ }
+ }
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ group.resume();
+ }
+ }
+ }
+
+ /**
+ * Sets whether this is a daemon {@code ThreadGroup} or not. Daemon
+ * thread groups are automatically destroyed when they become empty.
+ *
+ * @param isDaemon the new value
+ * @see #isDaemon
+ * @see #destroy
+ */
+ public final void setDaemon(boolean isDaemon) {
+ this.isDaemon = isDaemon;
+ }
+
+ /**
+ * Configures the maximum allowed priority for a {@code Thread} in this group and
+ * recursively in all its subgroups.
+ *
+ * <p>A caller can never increase the maximum priority of a thread group.
+ * Such an attempt will not result in an exception, it will
+ * simply leave the thread group with its current maximum priority.
+ *
+ * @param newMax the new maximum priority to be set
+ *
+ * @throws IllegalArgumentException if the new priority is greater than
+ * Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY
+ *
+ * @see #getMaxPriority
+ */
+ public final void setMaxPriority(int newMax) {
+ if (newMax <= this.maxPriority) {
+ if (newMax < Thread.MIN_PRIORITY) {
+ newMax = Thread.MIN_PRIORITY;
+ }
+
+ int parentPriority = parent == null ? newMax : parent.getMaxPriority();
+ this.maxPriority = parentPriority <= newMax ? parentPriority : newMax;
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ group.setMaxPriority(newMax);
+ }
+ }
+ }
+ }
+
+ /**
+ * Stops every thread in this group and recursively in all its subgroups.
+ *
+ * @see Thread#stop()
+ * @see Thread#stop(Throwable)
+ * @see ThreadDeath
+ *
+ * @deprecated Requires deprecated method Thread.stop().
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public final void stop() {
+ if (stopHelper()) {
+ Thread.currentThread().stop();
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private boolean stopHelper() {
+ boolean stopCurrent = false;
+ synchronized (threadRefs) {
+ Thread current = Thread.currentThread();
+ for (Thread thread : threads) {
+ if (thread == current) {
+ stopCurrent = true;
+ } else {
+ thread.stop();
+ }
+ }
+ }
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ stopCurrent |= group.stopHelper();
+ }
+ }
+ return stopCurrent;
+ }
+
+ /**
+ * Suspends every thread in this group and recursively in all its
+ * subgroups.
+ *
+ * @see Thread#suspend
+ * @see #resume
+ *
+ * @deprecated Requires deprecated method Thread.suspend().
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public final void suspend() {
+ if (suspendHelper()) {
+ Thread.currentThread().suspend();
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private boolean suspendHelper() {
+ boolean suspendCurrent = false;
+ synchronized (threadRefs) {
+ Thread current = Thread.currentThread();
+ for (Thread thread : threads) {
+ if (thread == current) {
+ suspendCurrent = true;
+ } else {
+ thread.suspend();
+ }
+ }
+ }
+ synchronized (groups) {
+ for (ThreadGroup group : groups) {
+ suspendCurrent |= group.suspendHelper();
+ }
+ }
+ return suspendCurrent;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName() + "[name=" + getName()
+ + ",maxPriority=" + getMaxPriority() + "]";
+ }
+
+ /**
+ * Handles uncaught exceptions. Any uncaught exception in any {@code Thread}
+ * is forwarded to the thread's {@code ThreadGroup} by invoking this
+ * method.
+ *
+ * <p>New code should use {@link Thread#setUncaughtExceptionHandler} instead of thread groups.
+ *
+ * @param t the Thread that terminated with an uncaught exception
+ * @param e the uncaught exception itself
+ */
+ public void uncaughtException(Thread t, Throwable e) {
+ if (parent != null) {
+ parent.uncaughtException(t, e);
+ } else if (Thread.getDefaultUncaughtExceptionHandler() != null) {
+ // TODO The spec is unclear regarding this. What do we do?
+ Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, e);
+ } else if (!(e instanceof ThreadDeath)) {
+ // No parent group, has to be 'system' Thread Group
+ e.printStackTrace(System.err);
+ }
+ }
+
+ /**
+ * Called by the Thread constructor.
+ */
+ final void addThread(Thread thread) throws IllegalThreadStateException {
+ synchronized (threadRefs) {
+ if (isDestroyed) {
+ throw new IllegalThreadStateException();
+ }
+ threadRefs.add(new WeakReference<Thread>(thread));
+ }
+ }
+
+ /**
+ * Called by the VM when a Thread dies.
+ */
+ final void removeThread(Thread thread) throws IllegalThreadStateException {
+ synchronized (threadRefs) {
+ for (Iterator<Thread> i = threads.iterator(); i.hasNext(); ) {
+ if (i.next().equals(thread)) {
+ i.remove();
+ break;
+ }
+ }
+ }
+ destroyIfEmptyDaemon();
+ }
+}
diff --git a/libart/src/main/java/java/lang/VMClassLoader.java b/libart/src/main/java/java/lang/VMClassLoader.java
new file mode 100644
index 0000000..d180a4d
--- /dev/null
+++ b/libart/src/main/java/java/lang/VMClassLoader.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+class VMClassLoader {
+
+ /**
+ * Get a resource from a file in the bootstrap class path.
+ *
+ * It would be simpler to just walk through the class path elements
+ * ourselves, but that would require reopening Jar files.
+ *
+ * We assume that the bootclasspath can't change once the VM has
+ * started. This assumption seems to be supported by the spec.
+ */
+ static URL getResource(String name) {
+ int numEntries = getBootClassPathSize();
+ for (int i = 0; i < numEntries; i++) {
+ String urlStr = getBootClassPathResource(name, i);
+ if (urlStr != null) {
+ try {
+ return new URL(urlStr);
+ } catch (MalformedURLException mue) {
+ mue.printStackTrace();
+ // unexpected; keep going
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Get an enumeration with all matching resources.
+ */
+ static List<URL> getResources(String name) {
+ ArrayList<URL> list = new ArrayList<URL>();
+ int numEntries = getBootClassPathSize();
+ for (int i = 0; i < numEntries; i++) {
+ String urlStr = getBootClassPathResource(name, i);
+ if (urlStr != null) {
+ try {
+ list.add(new URL(urlStr));
+ } catch (MalformedURLException mue) {
+ mue.printStackTrace();
+ // unexpected; keep going
+ }
+ }
+ }
+ return list;
+ }
+
+ native static Class findLoadedClass(ClassLoader cl, String name);
+
+ /**
+ * Boot class path manipulation, for getResources().
+ */
+ native private static int getBootClassPathSize();
+ native private static String getBootClassPathResource(String name, int index);
+}
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
new file mode 100644
index 0000000..ff52b41
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2012 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 java.lang.reflect;
+
+import com.android.dex.Dex;
+import java.lang.annotation.Annotation;
+import java.util.List;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.ListOfTypes;
+import libcore.reflect.Types;
+
+/**
+ * This class represents an abstract method. Abstract methods are either methods or constructors.
+ * @hide
+ */
+public abstract class AbstractMethod extends AccessibleObject {
+
+ protected final ArtMethod artMethod;
+
+ protected AbstractMethod(ArtMethod artMethod) {
+ if (artMethod == null) {
+ throw new NullPointerException("artMethod == null");
+ }
+ this.artMethod = artMethod;
+ }
+
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ return super.getAnnotation(annotationClass);
+ }
+
+ /**
+ * We insert native method stubs for abstract methods so we don't have to
+ * check the access flags at the time of the method call. This results in
+ * "native abstract" methods, which can't exist. If we see the "abstract"
+ * flag set, clear the "native" flag.
+ *
+ * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
+ * position, because the callers of this function are trying to convey
+ * the "traditional" meaning of the flags to their callers.
+ */
+ private static int fixMethodFlags(int flags) {
+ if ((flags & Modifier.ABSTRACT) != 0) {
+ flags &= ~Modifier.NATIVE;
+ }
+ flags &= ~Modifier.SYNCHRONIZED;
+ int ACC_DECLARED_SYNCHRONIZED = 0x00020000;
+ if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
+ flags |= Modifier.SYNCHRONIZED;
+ }
+ return flags & 0xffff; // mask out bits not used by Java
+ }
+
+ int getModifiers() {
+ return fixMethodFlags(artMethod.getAccessFlags());
+ }
+
+ boolean isVarArgs() {
+ return (artMethod.getAccessFlags() & Modifier.VARARGS) != 0;
+ }
+
+ boolean isBridge() {
+ return (artMethod.getAccessFlags() & Modifier.BRIDGE) != 0;
+ }
+
+ boolean isSynthetic() {
+ return (artMethod.getAccessFlags() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * @hide
+ */
+ public final int getAccessFlags() {
+ return artMethod.getAccessFlags();
+ }
+
+ /**
+ * Returns the class that declares this constructor or method.
+ */
+ Class<?> getDeclaringClass() {
+ return artMethod.getDeclaringClass();
+ }
+
+ /**
+ * Returns the index of this method's ID in its dex file.
+ *
+ * @hide
+ */
+ public final int getDexMethodIndex() {
+ return artMethod.getDexMethodIndex();
+ }
+
+ /**
+ * Returns the name of the method or constructor represented by this
+ * instance.
+ *
+ * @return the name of this method
+ */
+ abstract public String getName();
+
+ /**
+ * Returns an array of {@code Class} objects associated with the parameter types of this
+ * abstract method. If the method was declared with no parameters, an
+ * empty array will be returned.
+ *
+ * @return the parameter types
+ */
+ public Class<?>[] getParameterTypes() {
+ return artMethod.getParameterTypes();
+ }
+
+ /**
+ * Returns true if {@code other} has the same declaring class, name,
+ * parameters and return type as this method.
+ */
+ @Override public boolean equals(Object other) {
+ if (!(other instanceof AbstractMethod)) {
+ return false;
+ }
+ // exactly one instance of each member in this runtime
+ return this.artMethod == ((AbstractMethod) other).artMethod;
+ }
+
+ String toGenericString() {
+ return toGenericStringHelper();
+ }
+
+ Type[] getGenericParameterTypes() {
+ return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false);
+ }
+
+ Type[] getGenericExceptionTypes() {
+ return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false);
+ }
+
+ @Override public Annotation[] getDeclaredAnnotations() {
+ List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
+ return result.toArray(new Annotation[result.size()]);
+ }
+
+ @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+ return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ }
+
+ public Annotation[] getAnnotations() {
+ return super.getAnnotations();
+ }
+
+ /**
+ * Returns an array of arrays that represent the annotations of the formal
+ * parameters of this method. If there are no parameters on this method,
+ * then an empty array is returned. If there are no annotations set, then
+ * and array of empty arrays is returned.
+ *
+ * @return an array of arrays of {@code Annotation} instances
+ */
+ public abstract Annotation[][] getParameterAnnotations();
+
+ /**
+ * Returns the constructor's signature in non-printable form. This is called
+ * (only) from IO native code and needed for deriving the serialVersionUID
+ * of the class
+ *
+ * @return The constructor's signature.
+ */
+ @SuppressWarnings("unused")
+ abstract String getSignature();
+
+ static final class GenericInfo {
+ final ListOfTypes genericExceptionTypes;
+ final ListOfTypes genericParameterTypes;
+ final Type genericReturnType;
+ final TypeVariable<?>[] formalTypeParameters;
+
+ GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret,
+ TypeVariable<?>[] formal) {
+ genericExceptionTypes = exceptions;
+ genericParameterTypes = parameters;
+ genericReturnType = ret;
+ formalTypeParameters = formal;
+ }
+ }
+
+ /**
+ * Returns generic information associated with this method/constructor member.
+ */
+ final GenericInfo getMethodOrConstructorGenericInfo() {
+ String signatureAttribute = AnnotationAccess.getSignature(this);
+ Member member;
+ Class<?>[] exceptionTypes;
+ boolean method = this instanceof Method;
+ if (method) {
+ Method m = (Method) this;
+ member = m;
+ exceptionTypes = m.getExceptionTypes();
+ } else {
+ Constructor<?> c = (Constructor<?>) this;
+ member = c;
+ exceptionTypes = c.getExceptionTypes();
+ }
+ GenericSignatureParser parser =
+ new GenericSignatureParser(member.getDeclaringClass().getClassLoader());
+ if (method) {
+ parser.parseForMethod((GenericDeclaration) this, signatureAttribute, exceptionTypes);
+ } else {
+ parser.parseForConstructor((GenericDeclaration) this,
+ signatureAttribute,
+ exceptionTypes);
+ }
+ return new GenericInfo(parser.exceptionTypes, parser.parameterTypes,
+ parser.returnType, parser.formalTypeParameters);
+ }
+
+ /**
+ * Helper for Method and Constructor for toGenericString
+ */
+ final String toGenericStringHelper() {
+ StringBuilder sb = new StringBuilder(80);
+ GenericInfo info = getMethodOrConstructorGenericInfo();
+ int modifiers = ((Member)this).getModifiers();
+ // append modifiers if any
+ if (modifiers != 0) {
+ sb.append(Modifier.toString(modifiers & ~Modifier.VARARGS)).append(' ');
+ }
+ // append type parameters
+ if (info.formalTypeParameters != null && info.formalTypeParameters.length > 0) {
+ sb.append('<');
+ for (int i = 0; i < info.formalTypeParameters.length; i++) {
+ Types.appendGenericType(sb, info.formalTypeParameters[i]);
+ if (i < info.formalTypeParameters.length - 1) {
+ sb.append(",");
+ }
+ }
+ sb.append("> ");
+ }
+ Class<?> declaringClass = ((Member) this).getDeclaringClass();
+ if (this instanceof Constructor) {
+ // append constructor name
+ Types.appendTypeName(sb, declaringClass);
+ } else {
+ // append return type
+ Types.appendGenericType(sb, Types.getType(info.genericReturnType));
+ sb.append(' ');
+ // append method name
+ Types.appendTypeName(sb, declaringClass);
+ sb.append(".").append(((Method) this).getName());
+ }
+ // append parameters
+ sb.append('(');
+ Types.appendArrayGenericType(sb, info.genericParameterTypes.getResolvedTypes());
+ sb.append(')');
+ // append exceptions if any
+ Type[] genericExceptionTypeArray =
+ Types.getTypeArray(info.genericExceptionTypes, false);
+ if (genericExceptionTypeArray.length > 0) {
+ sb.append(" throws ");
+ Types.appendArrayGenericType(sb, genericExceptionTypeArray);
+ }
+ return sb.toString();
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/AccessibleObject.java b/libart/src/main/java/java/lang/reflect/AccessibleObject.java
new file mode 100644
index 0000000..dd57a12
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/AccessibleObject.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * {@code AccessibleObject} is the superclass of all member reflection classes
+ * (Field, Constructor, Method). AccessibleObject provides the ability to toggle
+ * a flag controlling access checks for these objects. By default, accessing a
+ * member (for example, setting a field or invoking a method) checks the
+ * validity of the access (for example, invoking a private method from outside
+ * the defining class is prohibited) and throws IllegalAccessException if the
+ * operation is not permitted. If the accessible flag is set to true, these
+ * checks are omitted. This allows privileged code, such as Java object
+ * serialization, object inspectors, and debuggers to have complete access to
+ * objects.
+ *
+ * @see Field
+ * @see Constructor
+ * @see Method
+ */
+public class AccessibleObject implements AnnotatedElement {
+ protected AccessibleObject() {
+ }
+
+ /**
+ * If true, object is accessible, bypassing normal access checks
+ */
+ private boolean flag = false;
+
+ /**
+ * Returns true if this object is accessible without access checks.
+ */
+ public boolean isAccessible() {
+ return flag;
+ }
+
+ /**
+ * Attempts to set the accessible flag. Setting this to true prevents {@code
+ * IllegalAccessExceptions}.
+ */
+ public void setAccessible(boolean flag) {
+ this.flag = flag;
+ }
+
+ /**
+ * Attempts to set the accessible flag for all objects in {@code objects}.
+ * Setting this to true prevents {@code IllegalAccessExceptions}.
+ */
+ public static void setAccessible(AccessibleObject[] objects, boolean flag) {
+ for (AccessibleObject object : objects) {
+ object.flag = flag;
+ }
+ }
+
+ @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public Annotation[] getDeclaredAnnotations() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public Annotation[] getAnnotations() {
+ // for all but Class, getAnnotations == getDeclaredAnnotations
+ return getDeclaredAnnotations();
+ }
+
+ @Override public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/ArtField.java b/libart/src/main/java/java/lang/reflect/ArtField.java
new file mode 100644
index 0000000..6fdcdb2
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/ArtField.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang.reflect;
+
+import com.android.dex.Dex;
+
+/**
+ * @hide
+ */
+public final class ArtField {
+
+ private Class<?> declaringClass;
+ /** Field access flags (modifiers) */
+ private int accessFlags;
+ /** Index into DexFile's field ids */
+ private int fieldDexIndex;
+ /** Offset of field in object or class */
+ private int offset;
+
+ /**
+ * Only created by art directly.
+ */
+ private ArtField() {}
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ int getDexFieldIndex() {
+ return fieldDexIndex;
+ }
+
+ int getOffset() {
+ return offset;
+ }
+
+ public String getName() {
+ if (fieldDexIndex == -1) {
+ // Proxy classes have 1 synthesized static field with no valid dex index
+ if (!declaringClass.isProxy()) {
+ throw new AssertionError();
+ }
+ return "throws";
+ }
+ Dex dex = declaringClass.getDex();
+ int nameIndex = dex.nameIndexFromFieldIndex(fieldDexIndex);
+ return declaringClass.getDexCacheString(dex, nameIndex);
+ }
+
+ Class<?> getDeclaringClass() {
+ return declaringClass;
+ }
+
+ Class<?> getType() {
+ if (fieldDexIndex == -1) {
+ // The type of the synthesized field in a Proxy class is Class[][]
+ if (!declaringClass.isProxy()) {
+ throw new AssertionError();
+ }
+ return Class[][].class;
+ }
+ Dex dex = declaringClass.getDex();
+ int typeIndex = dex.typeIndexFromFieldIndex(fieldDexIndex);
+ return declaringClass.getDexCacheType(dex, typeIndex);
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/ArtMethod.java b/libart/src/main/java/java/lang/reflect/ArtMethod.java
new file mode 100644
index 0000000..fd73331
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/ArtMethod.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2012 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 java.lang.reflect;
+
+import com.android.dex.Dex;
+import java.lang.annotation.Annotation;
+import libcore.reflect.AnnotationAccess;
+import libcore.util.EmptyArray;
+
+/**
+ * This class represents methods and constructors.
+ * @hide
+ */
+public final class ArtMethod {
+
+ /** Method's declaring class */
+ private Class<?> declaringClass;
+ /** Method access flags (modifiers) */
+ private int accessFlags;
+ /** DexFile index */
+ private int methodDexIndex;
+ /** Dispatch table entry */
+ private int methodIndex;
+ /** DexFile offset of CodeItem for this Method */
+ private int codeItemOffset;
+ /* ART compiler meta-data */
+ private int frameSizeInBytes;
+ private int coreSpillMask;
+ private int fpSpillMask;
+ private int mappingTable;
+ private int gcMap;
+ private int vmapTable;
+ /** ART: compiled managed code associated with this Method */
+ private int entryPointFromCompiledCode;
+ /** ART: entry point from interpreter associated with this Method */
+ private int entryPointFromInterpreter;
+ /** ART: if this is a native method, the native code that will be invoked */
+ private int nativeMethod;
+ /* ART: dex cache fast access */
+ private String[] dexCacheStrings;
+ Class<?>[] dexCacheResolvedTypes;
+ private ArtMethod[] dexCacheResolvedMethods;
+ private Object[] dexCacheInitializedStaticStorage;
+
+ /**
+ * Only created by art directly.
+ */
+ private ArtMethod() {}
+
+ Class getDeclaringClass() {
+ return declaringClass;
+ }
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ int getDexMethodIndex() {
+ return methodDexIndex;
+ }
+
+ public static String getMethodName(ArtMethod artMethod) {
+ artMethod = artMethod.findOverriddenMethodIfProxy();
+ Dex dex = artMethod.getDeclaringClass().getDex();
+ int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex());
+ // Note, in the case of a Proxy the dex cache strings are equal.
+ return artMethod.getDexCacheString(dex, nameIndex);
+ }
+
+ /**
+ * Returns true if the given parameters match those of the method in the given order.
+ *
+ * @hide
+ */
+ public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) {
+ Dex dex = artMethod.getDeclaringClass().getDex();
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex());
+ if (types.length != params.length) {
+ return false;
+ }
+ for (int i = 0; i < types.length; i++) {
+ if (artMethod.getDexCacheType(dex, types[i]) != params[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the given parameters match those of this method in the given order.
+ *
+ * @hide
+ */
+ public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) {
+ return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params);
+ }
+
+ Class<?>[] getParameterTypes() {
+ Dex dex = getDeclaringClass().getDex();
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
+ if (types.length == 0) {
+ return EmptyArray.CLASS;
+ }
+ Class<?>[] parametersArray = new Class[types.length];
+ for (int i = 0; i < types.length; i++) {
+ // Note, in the case of a Proxy the dex cache types are equal.
+ parametersArray[i] = getDexCacheType(dex, types[i]);
+ }
+ return parametersArray;
+ }
+
+ Class<?> getReturnType() {
+ Dex dex = declaringClass.getDex();
+ int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(methodDexIndex);
+ // Note, in the case of a Proxy the dex cache types are equal.
+ return getDexCacheType(dex, returnTypeIndex);
+ }
+
+ /**
+ * Performs a comparison of the parameters to this method with the given parameters.
+ *
+ * @hide
+ */
+ int compareParameters(Class<?>[] params) {
+ Dex dex = getDeclaringClass().getDex();
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
+ int length = Math.min(types.length, params.length);
+ for (int i = 0; i < length; i++) {
+ Class<?> aType = getDexCacheType(dex, types[i]);
+ Class<?> bType = params[i];
+ if (aType != bType) {
+ int comparison = aType.getName().compareTo(bType.getName());
+ if (comparison != 0) {
+ return comparison;
+ }
+ }
+ }
+ return types.length - params.length;
+ }
+
+ Annotation[][] getParameterAnnotations() {
+ return AnnotationAccess.getParameterAnnotations(declaringClass, methodDexIndex);
+ }
+
+ /**
+ * Returns a string from the dex cache, computing the string from the dex file if necessary.
+ * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in
+ * Method we can avoid one indirection.
+ */
+ private String getDexCacheString(Dex dex, int dexStringIndex) {
+ String s = (String) dexCacheStrings[dexStringIndex];
+ if (s == null) {
+ s = dex.strings().get(dexStringIndex).intern();
+ dexCacheStrings[dexStringIndex] = s;
+ }
+ return s;
+ }
+
+ /**
+ * Returns a resolved type from the dex cache, computing the string from the dex file if
+ * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)},
+ * but in Method we can avoid one indirection.
+ */
+ private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
+ Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex];
+ if (resolvedType == null) {
+ resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex);
+ }
+ return resolvedType;
+ }
+
+ /**
+ * Returns the {@code ArtMethod} that this method overrides for
+ * proxy methods, otherwise returns this method. Used to determine
+ * the interface method overridden by a proxy method (as the proxy
+ * method doesn't directly support operations such as {@link
+ * Method#getName}).
+ */
+ ArtMethod findOverriddenMethodIfProxy() {
+ if (declaringClass.isProxy()) {
+ // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in
+ // Method refers to the original interface's dex cache and is ensured to be resolved by
+ // proxy generation.
+ return dexCacheResolvedMethods[methodDexIndex];
+ }
+ return this;
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
new file mode 100644
index 0000000..b3df2f0
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang.reflect;
+
+import com.android.dex.Dex;
+import java.lang.annotation.Annotation;
+import java.util.Comparator;
+import java.util.List;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.Types;
+
+/**
+ * This class represents a constructor. Information about the constructor can be
+ * accessed, and the constructor can be invoked dynamically.
+ *
+ * @param <T> the class that declares this constructor
+ */
+public final class Constructor<T> extends AbstractMethod implements GenericDeclaration, Member {
+
+ private static final Comparator<Method> ORDER_BY_SIGNATURE = null; // Unused; must match Method.
+
+ /**
+ * @hide
+ */
+ public Constructor(ArtMethod artMethod) {
+ super(artMethod);
+ }
+
+ public Annotation[] getAnnotations() {
+ return super.getAnnotations();
+ }
+
+ /**
+ * Returns the modifiers for this constructor. The {@link Modifier} class
+ * should be used to decode the result.
+ */
+ @Override public int getModifiers() {
+ return super.getModifiers();
+ }
+
+ /**
+ * Returns true if this constructor takes a variable number of arguments.
+ */
+ public boolean isVarArgs() {
+ return super.isVarArgs();
+ }
+
+ /**
+ * Returns true if this constructor is synthetic (artificially introduced by the compiler).
+ */
+ @Override public boolean isSynthetic() {
+ return super.isSynthetic();
+ }
+
+ /**
+ * Returns the name of this constructor.
+ */
+ @Override public String getName() {
+ return getDeclaringClass().getName();
+ }
+
+ /**
+ * Returns the class that declares this constructor.
+ */
+ @Override public Class<T> getDeclaringClass() {
+ return (Class<T>) super.getDeclaringClass();
+ }
+
+ /**
+ * Returns the exception types as an array of {@code Class} instances. If
+ * this constructor has no declared exceptions, an empty array will be
+ * returned.
+ */
+ public Class<?>[] getExceptionTypes() {
+ // TODO: use dex cache to speed looking up class
+ return AnnotationAccess.getExceptions(this);
+ }
+
+ /**
+ * Returns an array of the {@code Class} objects associated with the
+ * parameter types of this constructor. If the constructor was declared with
+ * no parameters, an empty array will be returned.
+ */
+ public Class<?>[] getParameterTypes() {
+ return super.getParameterTypes();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code getDeclaringClass().getName().hashCode()}.
+ */
+ @Override public int hashCode() {
+ return getDeclaringClass().getName().hashCode();
+ }
+
+ /**
+ * Returns true if {@code other} has the same declaring class and parameters
+ * as this constructor.
+ */
+ @Override public boolean equals(Object other) {
+ return super.equals(other);
+ }
+
+ @Override public TypeVariable<Constructor<T>>[] getTypeParameters() {
+ GenericInfo info = getMethodOrConstructorGenericInfo();
+ return (TypeVariable<Constructor<T>>[]) info.formalTypeParameters.clone();
+ }
+
+ /**
+ * Returns the string representation of the constructor's declaration,
+ * including the type parameters.
+ *
+ * @return the string representation of the constructor's declaration
+ */
+ public String toGenericString() {
+ return super.toGenericString();
+ }
+
+ /**
+ * Returns the generic parameter types as an array of {@code Type}
+ * instances, in declaration order. If this constructor has no generic
+ * parameters, an empty array is returned.
+ *
+ * @return the parameter types
+ *
+ * @throws GenericSignatureFormatError
+ * if the generic constructor signature is invalid
+ * @throws TypeNotPresentException
+ * if any parameter type points to a missing type
+ * @throws MalformedParameterizedTypeException
+ * if any parameter type points to a type that cannot be
+ * instantiated for some reason
+ */
+ public Type[] getGenericParameterTypes() {
+ return super.getGenericParameterTypes();
+ }
+
+ /**
+ * Returns the exception types as an array of {@code Type} instances. If
+ * this constructor has no declared exceptions, an empty array will be
+ * returned.
+ *
+ * @return an array of generic exception types
+ *
+ * @throws GenericSignatureFormatError
+ * if the generic constructor signature is invalid
+ * @throws TypeNotPresentException
+ * if any exception type points to a missing type
+ * @throws MalformedParameterizedTypeException
+ * if any exception type points to a type that cannot be
+ * instantiated for some reason
+ */
+ public Type[] getGenericExceptionTypes() {
+ return super.getGenericExceptionTypes();
+ }
+
+ @Override public Annotation[] getDeclaredAnnotations() {
+ List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
+ return result.toArray(new Annotation[result.size()]);
+ }
+
+ @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+ return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ }
+
+ @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+ return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ }
+
+ /**
+ * Returns an array of arrays that represent the annotations of the formal
+ * parameters of this constructor. If there are no parameters on this
+ * constructor, then an empty array is returned. If there are no annotations
+ * set, then an array of empty arrays is returned.
+ *
+ * @return an array of arrays of {@code Annotation} instances
+ */
+ public Annotation[][] getParameterAnnotations() {
+ return artMethod.getParameterAnnotations();
+ }
+
+ /**
+ * Returns the constructor's signature in non-printable form. This is called
+ * (only) from IO native code and needed for deriving the serialVersionUID
+ * of the class
+ *
+ * @return the constructor's signature
+ */
+ @SuppressWarnings("unused")
+ String getSignature() {
+ StringBuilder result = new StringBuilder();
+
+ result.append('(');
+ Class<?>[] parameterTypes = getParameterTypes();
+ for (Class<?> parameterType : parameterTypes) {
+ result.append(Types.getSignature(parameterType));
+ }
+ result.append(")V");
+
+ return result.toString();
+ }
+
+ /**
+ * Returns a new instance of the declaring class, initialized by dynamically
+ * invoking the constructor represented by this {@code Constructor} object.
+ * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... ,
+ * argN)} This method performs the following:
+ * <ul>
+ * <li>A new instance of the declaring class is created. If the declaring
+ * class cannot be instantiated (i.e. abstract class, an interface, an array
+ * type, or a primitive type) then an InstantiationException is thrown.</li>
+ * <li>If this Constructor object is enforcing access control (see
+ * {@link AccessibleObject}) and this constructor is not accessible from the
+ * current context, an IllegalAccessException is thrown.</li>
+ * <li>If the number of arguments passed and the number of parameters do not
+ * match, an IllegalArgumentException is thrown.</li>
+ * <li>For each argument passed:
+ * <ul>
+ * <li>If the corresponding parameter type is a primitive type, the argument
+ * is unboxed. If the unboxing fails, an IllegalArgumentException is
+ * thrown.</li>
+ * <li>If the resulting argument cannot be converted to the parameter type
+ * via a widening conversion, an IllegalArgumentException is thrown.</li>
+ * </ul>
+ * <li>The constructor represented by this {@code Constructor} object is
+ * then invoked. If an exception is thrown during the invocation, it is
+ * caught and wrapped in an InvocationTargetException. This exception is
+ * then thrown. If the invocation completes normally, the newly initialized
+ * object is returned.
+ * </ul>
+ *
+ * @param args
+ * the arguments to the constructor
+ *
+ * @return the new, initialized, object
+ *
+ * @exception InstantiationException
+ * if the class cannot be instantiated
+ * @exception IllegalAccessException
+ * if this constructor is not accessible
+ * @exception IllegalArgumentException
+ * if an incorrect number of arguments are passed, or an
+ * argument could not be converted by a widening conversion
+ * @exception InvocationTargetException
+ * if an exception was thrown by the invoked constructor
+ *
+ * @see AccessibleObject
+ */
+ public native T newInstance(Object... args) throws InstantiationException,
+ IllegalAccessException, IllegalArgumentException, InvocationTargetException;
+
+ /**
+ * Returns a string containing a concise, human-readable description of this
+ * constructor. The format of the string is:
+ *
+ * <ol>
+ * <li>modifiers (if any)
+ * <li>declaring class name
+ * <li>'('
+ * <li>parameter types, separated by ',' (if any)
+ * <li>')'
+ * <li>'throws' plus exception types, separated by ',' (if any)
+ * </ol>
+ *
+ * For example:
+ * {@code public String(byte[],String) throws UnsupportedEncodingException}
+ *
+ * @return a printable representation for this constructor
+ */
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
+
+ if (result.length() != 0) {
+ result.append(' ');
+ }
+ result.append(getDeclaringClass().getName());
+ result.append("(");
+ Class<?>[] parameterTypes = getParameterTypes();
+ result.append(Types.toString(parameterTypes));
+ result.append(")");
+ Class<?>[] exceptionTypes = getExceptionTypes();
+ if (exceptionTypes.length > 0) {
+ result.append(" throws ");
+ result.append(Types.toString(exceptionTypes));
+ }
+
+ return result.toString();
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/Field.java b/libart/src/main/java/java/lang/reflect/Field.java
new file mode 100644
index 0000000..4e982c7
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/Field.java
@@ -0,0 +1,792 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang.reflect;
+
+import com.android.dex.Dex;
+import java.lang.annotation.Annotation;
+import java.util.Comparator;
+import java.util.List;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.Types;
+
+/**
+ * This class represents a field. Information about the field can be accessed,
+ * and the field's value can be accessed dynamically.
+ */
+public final class Field extends AccessibleObject implements Member {
+
+ /**
+ * Orders fields by their name and declaring class.
+ *
+ * @hide
+ */
+ public static final Comparator<Field> ORDER_BY_NAME_AND_DECLARING_CLASS
+ = new Comparator<Field>() {
+ @Override public int compare(Field a, Field b) {
+ if (a == b) {
+ return 0;
+ }
+ int comparison = a.getName().compareTo(b.getName());
+ if (comparison != 0) {
+ return comparison;
+ }
+ Class<?> aType = a.getDeclaringClass();
+ Class<?> bType = b.getDeclaringClass();
+ if (aType == bType) {
+ return 0;
+ } else {
+ return aType.getName().compareTo(bType.getName());
+ }
+ }
+ };
+
+ private final ArtField artField;
+
+ /**
+ * @hide
+ */
+ public Field(ArtField artField) {
+ if (artField == null) {
+ throw new NullPointerException("artField == null");
+ }
+ this.artField = artField;
+ }
+
+ /**
+ * Returns the modifiers for this field. The {@link Modifier} class should
+ * be used to decode the result.
+ *
+ * @return the modifiers for this field
+ * @see Modifier
+ */
+ @Override public int getModifiers() {
+ return artField.getAccessFlags() & 0xffff; // mask out bits not used by Java
+ }
+
+ /**
+ * Indicates whether or not this field is an enumeration constant.
+ *
+ * @return {@code true} if this field is an enumeration constant, {@code
+ * false} otherwise
+ */
+ public boolean isEnumConstant() {
+ return (artField.getAccessFlags() & Modifier.ENUM) != 0;
+ }
+
+ /**
+ * Indicates whether or not this field is synthetic.
+ *
+ * @return {@code true} if this field is synthetic, {@code false} otherwise
+ */
+ @Override public boolean isSynthetic() {
+ return (artField.getAccessFlags() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * Returns the name of this field.
+ *
+ * @return the name of this field
+ */
+ @Override public String getName() {
+ return artField.getName();
+ }
+
+ @Override public Class<?> getDeclaringClass() {
+ return artField.getDeclaringClass();
+ }
+
+ /**
+ * Return the {@link Class} associated with the type of this field.
+ *
+ * @return the type of this field
+ */
+ public Class<?> getType() {
+ return artField.getType();
+ }
+
+ /**
+ * Returns the index of this field's ID in its dex file.
+ *
+ * @hide
+ */
+ public int getDexFieldIndex() {
+ return artField.getDexFieldIndex();
+ }
+
+ /**
+ * Returns the offset of the field within an instance, or for static fields, the class.
+ *
+ * @hide
+ */
+ public int getOffset() {
+ return artField.getOffset();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code getDeclaringClass().getName().hashCode() ^ getName().hashCode()}.
+ */
+ @Override public int hashCode() {
+ return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
+ }
+
+ /**
+ * Returns true if {@code other} has the same declaring class, name and type
+ * as this field.
+ */
+ @Override public boolean equals(Object other) {
+ if (!(other instanceof Field)) {
+ return false;
+ }
+ // exactly one instance of each member in this runtime
+ return this.artField == ((Field) other).artField;
+ }
+
+ /**
+ * Returns the string representation of this field, including the field's
+ * generic type.
+ *
+ * @return the string representation of this field
+ */
+ public String toGenericString() {
+ StringBuilder sb = new StringBuilder(80);
+ // append modifiers if any
+ int modifier = getModifiers();
+ if (modifier != 0) {
+ sb.append(Modifier.toString(modifier)).append(' ');
+ }
+ // append generic type
+ Types.appendGenericType(sb, getGenericType());
+ sb.append(' ');
+ // append full field name
+ sb.append(getDeclaringClass().getName()).append('.').append(getName());
+ return sb.toString();
+ }
+
+ /**
+ * Returns the generic type of this field.
+ *
+ * @return the generic type
+ * @throws GenericSignatureFormatError
+ * if the generic field signature is invalid
+ * @throws TypeNotPresentException
+ * if the generic type points to a missing type
+ * @throws MalformedParameterizedTypeException
+ * if the generic type points to a type that cannot be
+ * instantiated for some reason
+ */
+ public Type getGenericType() {
+ String signatureAttribute = AnnotationAccess.getSignature(this);
+ Class<?> declaringClass = getDeclaringClass();
+ ClassLoader cl = declaringClass.getClassLoader();
+ GenericSignatureParser parser = new GenericSignatureParser(cl);
+ parser.parseForField(declaringClass, signatureAttribute);
+ Type genericType = parser.fieldType;
+ if (genericType == null) {
+ genericType = getType();
+ }
+ return genericType;
+ }
+
+ /**
+ * Returns the constructor's signature in non-printable form. This is called
+ * (only) from IO native code and needed for deriving the serialVersionUID
+ * of the class
+ */
+ @SuppressWarnings("unused")
+ private String getSignature() {
+ return Types.getSignature(getType());
+ }
+
+ @Override public Annotation[] getDeclaredAnnotations() {
+ List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
+ return result.toArray(new Annotation[result.size()]);
+ }
+
+ @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+ return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ }
+
+ @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+ return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ }
+
+ /**
+ * Returns the value of the field in the specified object. This reproduces
+ * the effect of {@code object.fieldName}
+ *
+ * <p>If the type of this field is a primitive type, the field value is
+ * automatically boxed.
+ *
+ * <p>If this field is static, the object argument is ignored.
+ * Otherwise, if the object is null, a NullPointerException is thrown. If
+ * the object is not an instance of the declaring class of the method, an
+ * IllegalArgumentException is thrown.
+ *
+ * <p>If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value, possibly boxed
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native Object get(Object object) throws IllegalAccessException, IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as a {@code
+ * boolean}. This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native boolean getBoolean(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as a {@code byte}.
+ * This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native byte getByte(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as a {@code char}.
+ * This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native char getChar(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as a {@code
+ * double}. This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native double getDouble(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as a {@code float}
+ * . This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native float getFloat(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as an {@code int}.
+ * This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native int getInt(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as a {@code long}.
+ * This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native long getLong(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns the value of the field in the specified object as a {@code short}
+ * . This reproduces the effect of {@code object.fieldName}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @return the field value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native short getShort(Object object) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the value. This
+ * reproduces the effect of {@code object.fieldName = value}
+ *
+ * <p>If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ *
+ * <p>If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ *
+ * <p>If the field type is a primitive type, the value is automatically
+ * unboxed. If the unboxing fails, an IllegalArgumentException is thrown. If
+ * the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void set(Object object, Object value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the {@code
+ * boolean} value. This reproduces the effect of {@code object.fieldName =
+ * value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setBoolean(Object object, boolean value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the {@code byte}
+ * value. This reproduces the effect of {@code object.fieldName = value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setByte(Object object, byte value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the {@code char}
+ * value. This reproduces the effect of {@code object.fieldName = value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setChar(Object object, char value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the {@code double}
+ * value. This reproduces the effect of {@code object.fieldName = value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setDouble(Object object, double value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the {@code float}
+ * value. This reproduces the effect of {@code object.fieldName = value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setFloat(Object object, float value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Set the value of the field in the specified object to the {@code int}
+ * value. This reproduces the effect of {@code object.fieldName = value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setInt(Object object, int value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the {@code long}
+ * value. This reproduces the effect of {@code object.fieldName = value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setLong(Object object, long value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Sets the value of the field in the specified object to the {@code short}
+ * value. This reproduces the effect of {@code object.fieldName = value}
+ * <p>
+ * If this field is static, the object argument is ignored.
+ * Otherwise, if the object is {@code null}, a NullPointerException is
+ * thrown. If the object is not an instance of the declaring class of the
+ * method, an IllegalArgumentException is thrown.
+ * <p>
+ * If this Field object is enforcing access control (see AccessibleObject)
+ * and this field is not accessible from the current context, an
+ * IllegalAccessException is thrown.
+ * <p>
+ * If the value cannot be converted to the field type via a widening
+ * conversion, an IllegalArgumentException is thrown.
+ *
+ * @param object
+ * the object to access
+ * @param value
+ * the new value
+ * @throws NullPointerException
+ * if the object is {@code null} and the field is non-static
+ * @throws IllegalArgumentException
+ * if the object is not compatible with the declaring class
+ * @throws IllegalAccessException
+ * if this field is not accessible
+ */
+ public native void setShort(Object object, short value) throws IllegalAccessException,
+ IllegalArgumentException;
+
+ /**
+ * Returns a string containing a concise, human-readable description of this
+ * field.
+ * <p>
+ * The format of the string is:
+ * <ol>
+ * <li>modifiers (if any)
+ * <li>type
+ * <li>declaring class name
+ * <li>'.'
+ * <li>field name
+ * </ol>
+ * <p>
+ * For example: {@code public static java.io.InputStream
+ * java.lang.System.in}
+ *
+ * @return a printable representation for this field
+ */
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
+ if (result.length() != 0) {
+ result.append(' ');
+ }
+ Types.appendTypeName(result, getType());
+ result.append(' ');
+ result.append(getDeclaringClass().getName());
+ result.append('.');
+ result.append(getName());
+ return result.toString();
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java
new file mode 100644
index 0000000..3089932
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/Method.java
@@ -0,0 +1,439 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 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 java.lang.reflect;
+
+import com.android.dex.Dex;
+import java.lang.annotation.Annotation;
+import java.util.Comparator;
+import java.util.List;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.Types;
+
+/**
+ * This class represents a method. Information about the method can be accessed,
+ * and the method can be invoked dynamically.
+ */
+public final class Method extends AbstractMethod implements GenericDeclaration, Member {
+
+ /**
+ * Orders methods by their name, parameters and return type.
+ *
+ * @hide
+ */
+ public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() {
+ @Override public int compare(Method a, Method b) {
+ if (a == b) {
+ return 0;
+ }
+ int comparison = a.getName().compareTo(b.getName());
+ if (comparison == 0) {
+ comparison = a.artMethod.findOverriddenMethodIfProxy().compareParameters(
+ b.getParameterTypes());
+ if (comparison == 0) {
+ // This is necessary for methods that have covariant return types.
+ Class<?> aReturnType = a.getReturnType();
+ Class<?> bReturnType = b.getReturnType();
+ if (aReturnType == bReturnType) {
+ comparison = 0;
+ } else {
+ comparison = aReturnType.getName().compareTo(bReturnType.getName());
+ }
+ }
+ }
+ return comparison;
+ }
+ };
+
+ /**
+ * @hide
+ */
+ public Method(ArtMethod artMethod) {
+ super(artMethod);
+ }
+
+ ArtMethod getArtMethod() {
+ return artMethod;
+ }
+
+ public Annotation[] getAnnotations() {
+ return super.getAnnotations();
+ }
+
+ /**
+ * Returns the modifiers for this method. The {@link Modifier} class should
+ * be used to decode the result.
+ *
+ * @return the modifiers for this method
+ *
+ * @see Modifier
+ */
+ @Override public int getModifiers() {
+ return super.getModifiers();
+ }
+
+ /**
+ * Indicates whether or not this method takes a variable number argument.
+ *
+ * @return {@code true} if a vararg is declared, {@code false} otherwise
+ */
+ public boolean isVarArgs() {
+ return super.isVarArgs();
+ }
+
+ /**
+ * Indicates whether or not this method is a bridge.
+ *
+ * @return {@code true} if this method is a bridge, {@code false} otherwise
+ */
+ public boolean isBridge() {
+ return super.isBridge();
+
+ }
+
+ /**
+ * Indicates whether or not this method is synthetic.
+ *
+ * @return {@code true} if this method is synthetic, {@code false} otherwise
+ */
+ @Override public boolean isSynthetic() {
+ return super.isSynthetic();
+ }
+
+ /**
+ * Returns the name of the method represented by this {@code Method}
+ * instance.
+ *
+ * @return the name of this method
+ */
+ @Override public String getName() {
+ return ArtMethod.getMethodName(artMethod);
+ }
+
+ /**
+ * Returns the class that declares this method.
+ */
+ @Override public Class<?> getDeclaringClass() {
+ return super.getDeclaringClass();
+ }
+
+ /**
+ * Returns the exception types as an array of {@code Class} instances. If
+ * this method has no declared exceptions, an empty array is returned.
+ *
+ * @return the declared exception classes
+ */
+ public Class<?>[] getExceptionTypes() {
+ if (getDeclaringClass().isProxy()) {
+ return getExceptionTypesNative();
+ } else {
+ // TODO: use dex cache to speed looking up class
+ return AnnotationAccess.getExceptions(this);
+ }
+ }
+
+ private native Class<?>[] getExceptionTypesNative();
+
+ /**
+ * Returns an array of {@code Class} objects associated with the parameter
+ * types of this method. If the method was declared with no parameters, an
+ * empty array will be returned.
+ *
+ * @return the parameter types
+ */
+ @Override public Class<?>[] getParameterTypes() {
+ return artMethod.findOverriddenMethodIfProxy().getParameterTypes();
+ }
+
+ /**
+ * Returns the {@code Class} associated with the return type of this
+ * method.
+ *
+ * @return the return type
+ */
+ public Class<?> getReturnType() {
+ return artMethod.findOverriddenMethodIfProxy().getReturnType();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code getDeclaringClass().getName().hashCode() ^ getName().hashCode()}.
+ */
+ @Override public int hashCode() {
+ return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
+ }
+
+ /**
+ * Returns true if {@code other} has the same declaring class, name,
+ * parameters and return type as this method.
+ */
+ @Override public boolean equals(Object other) {
+ return super.equals(other);
+ }
+
+ /**
+ * Returns true if this and {@code method} have the same name and the same
+ * parameters in the same order. Such methods can share implementation if
+ * one method's return types is assignable to the other.
+ *
+ * @hide needed by Proxy
+ */
+ boolean equalNameAndParameters(Method m) {
+ return getName().equals(m.getName()) &&
+ ArtMethod.equalMethodParameters(artMethod,m.getParameterTypes());
+ }
+
+ /**
+ * Returns the string representation of the method's declaration, including
+ * the type parameters.
+ *
+ * @return the string representation of this method
+ */
+ public String toGenericString() {
+ return super.toGenericString();
+ }
+
+ @Override public TypeVariable<Method>[] getTypeParameters() {
+ GenericInfo info = getMethodOrConstructorGenericInfo();
+ return (TypeVariable<Method>[]) info.formalTypeParameters.clone();
+ }
+
+ /**
+ * Returns the parameter types as an array of {@code Type} instances, in
+ * declaration order. If this method has no parameters, an empty array is
+ * returned.
+ *
+ * @return the parameter types
+ *
+ * @throws GenericSignatureFormatError
+ * if the generic method signature is invalid
+ * @throws TypeNotPresentException
+ * if any parameter type points to a missing type
+ * @throws MalformedParameterizedTypeException
+ * if any parameter type points to a type that cannot be
+ * instantiated for some reason
+ */
+ public Type[] getGenericParameterTypes() {
+ return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false);
+ }
+
+ @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+ return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ }
+
+ /**
+ * Returns the exception types as an array of {@code Type} instances. If
+ * this method has no declared exceptions, an empty array will be returned.
+ *
+ * @return an array of generic exception types
+ *
+ * @throws GenericSignatureFormatError
+ * if the generic method signature is invalid
+ * @throws TypeNotPresentException
+ * if any exception type points to a missing type
+ * @throws MalformedParameterizedTypeException
+ * if any exception type points to a type that cannot be
+ * instantiated for some reason
+ */
+ public Type[] getGenericExceptionTypes() {
+ return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false);
+ }
+
+ /**
+ * Returns the return type of this method as a {@code Type} instance.
+ *
+ * @return the return type of this method
+ *
+ * @throws GenericSignatureFormatError
+ * if the generic method signature is invalid
+ * @throws TypeNotPresentException
+ * if the return type points to a missing type
+ * @throws MalformedParameterizedTypeException
+ * if the return type points to a type that cannot be
+ * instantiated for some reason
+ */
+ public Type getGenericReturnType() {
+ return Types.getType(getMethodOrConstructorGenericInfo().genericReturnType);
+ }
+
+ @Override public Annotation[] getDeclaredAnnotations() {
+ List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
+ return result.toArray(new Annotation[result.size()]);
+ }
+
+ @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+ return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ }
+
+ /**
+ * Returns an array of arrays that represent the annotations of the formal
+ * parameters of this method. If there are no parameters on this method,
+ * then an empty array is returned. If there are no annotations set, then
+ * and array of empty arrays is returned.
+ *
+ * @return an array of arrays of {@code Annotation} instances
+ */
+ public Annotation[][] getParameterAnnotations() {
+ return artMethod.findOverriddenMethodIfProxy().getParameterAnnotations();
+ }
+
+ /**
+ * Returns the default value for the annotation member represented by this
+ * method.
+ *
+ * @return the default value, or {@code null} if none
+ *
+ * @throws TypeNotPresentException
+ * if this annotation member is of type {@code Class} and no
+ * definition can be found
+ */
+ public Object getDefaultValue() {
+ return AnnotationAccess.getDefaultValue(this);
+ }
+
+ /**
+ * Returns the result of dynamically invoking this method. Equivalent to
+ * {@code receiver.methodName(arg1, arg2, ... , argN)}.
+ *
+ * <p>If the method is static, the receiver argument is ignored (and may be null).
+ *
+ * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of
+ * allocating an empty array.
+ *
+ * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the
+ * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and
+ * the reflection machinery does not do this for you. (It couldn't, because it would be
+ * ambiguous.)
+ *
+ * <p>Reflective method invocation follows the usual process for method lookup.
+ *
+ * <p>If an exception is thrown during the invocation it is caught and
+ * wrapped in an InvocationTargetException. This exception is then thrown.
+ *
+ * <p>If the invocation completes normally, the return value itself is
+ * returned. If the method is declared to return a primitive type, the
+ * return value is boxed. If the return type is void, null is returned.
+ *
+ * @param receiver
+ * the object on which to call this method (or null for static methods)
+ * @param args
+ * the arguments to the method
+ * @return the result
+ *
+ * @throws NullPointerException
+ * if {@code receiver == null} for a non-static method
+ * @throws IllegalAccessException
+ * if this method is not accessible (see {@link AccessibleObject})
+ * @throws IllegalArgumentException
+ * if the number of arguments doesn't match the number of parameters, the receiver
+ * is incompatible with the declaring class, or an argument could not be unboxed
+ * or converted by a widening conversion to the corresponding parameter type
+ * @throws InvocationTargetException
+ * if an exception was thrown by the invoked method
+ */
+ public native Object invoke(Object receiver, Object... args)
+ throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
+
+ /**
+ * Returns a string containing a concise, human-readable description of this
+ * method. The format of the string is:
+ *
+ * <ol>
+ * <li>modifiers (if any)
+ * <li>return type or 'void'
+ * <li>declaring class name
+ * <li>'('
+ * <li>parameter types, separated by ',' (if any)
+ * <li>')'
+ * <li>'throws' plus exception types, separated by ',' (if any)
+ * </ol>
+ *
+ * For example: {@code public native Object
+ * java.lang.Method.invoke(Object,Object) throws
+ * IllegalAccessException,IllegalArgumentException
+ * ,InvocationTargetException}
+ *
+ * @return a printable representation for this method
+ */
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
+
+ if (result.length() != 0) {
+ result.append(' ');
+ }
+ result.append(getReturnType().getName());
+ result.append(' ');
+ result.append(getDeclaringClass().getName());
+ result.append('.');
+ result.append(getName());
+ result.append("(");
+ Class<?>[] parameterTypes = getParameterTypes();
+ result.append(Types.toString(parameterTypes));
+ result.append(")");
+ Class<?>[] exceptionTypes = getExceptionTypes();
+ if (exceptionTypes.length != 0) {
+ result.append(" throws ");
+ result.append(Types.toString(exceptionTypes));
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns the constructor's signature in non-printable form. This is called
+ * (only) from IO native code and needed for deriving the serialVersionUID
+ * of the class
+ *
+ * @return The constructor's signature.
+ */
+ @SuppressWarnings("unused")
+ String getSignature() {
+ StringBuilder result = new StringBuilder();
+
+ result.append('(');
+ Class<?>[] parameterTypes = getParameterTypes();
+ for (Class<?> parameterType : parameterTypes) {
+ result.append(Types.getSignature(parameterType));
+ }
+ result.append(')');
+ result.append(Types.getSignature(getReturnType()));
+
+ return result.toString();
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/Proxy.java b/libart/src/main/java/java/lang/reflect/Proxy.java
new file mode 100644
index 0000000..51b3ad5
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/Proxy.java
@@ -0,0 +1,381 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 java.lang.reflect;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import libcore.util.EmptyArray;
+
+/**
+ * {@code Proxy} defines methods for creating dynamic proxy classes and instances.
+ * A proxy class implements a declared set of interfaces and delegates method
+ * invocations to an {@code InvocationHandler}.
+ *
+ * @see InvocationHandler
+ * @since 1.3
+ */
+public class Proxy implements Serializable {
+
+ private static final long serialVersionUID = -2222568056686623797L;
+
+ private static int NextClassNameIndex = 0;
+
+ /**
+ * Orders methods by their name, parameters, return type and inheritance relationship.
+ *
+ * @hide
+ */
+ private static final Comparator<Method> ORDER_BY_SIGNATURE_AND_SUBTYPE = new Comparator<Method>() {
+ @Override public int compare(Method a, Method b) {
+ int comparison = Method.ORDER_BY_SIGNATURE.compare(a, b);
+ if (comparison != 0) {
+ return comparison;
+ }
+ Class<?> aClass = a.getDeclaringClass();
+ Class<?> bClass = b.getDeclaringClass();
+ if (aClass == bClass) {
+ return 0;
+ } else if (aClass.isAssignableFrom(bClass)) {
+ return 1;
+ } else if (bClass.isAssignableFrom(aClass)) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ };
+
+ /** The invocation handler on which the method calls are dispatched. */
+ protected InvocationHandler h;
+
+ @SuppressWarnings("unused")
+ private Proxy() {
+ }
+
+ /**
+ * Constructs a new {@code Proxy} instance with the specified invocation
+ * handler.
+ *
+ * @param h
+ * the invocation handler for the newly created proxy
+ */
+ protected Proxy(InvocationHandler h) {
+ this.h = h;
+ }
+
+ /**
+ * Returns the dynamically built {@code Class} for the specified interfaces.
+ * Creates a new {@code Class} when necessary. The order of the interfaces
+ * is relevant. Invocations of this method with the same interfaces but
+ * different order result in different generated classes. The interfaces
+ * must be visible from the supplied class loader; no duplicates are
+ * permitted. All non-public interfaces must be defined in the same package.
+ *
+ * @param loader
+ * the class loader that will define the proxy class
+ * @param interfaces
+ * an array of {@code Class} objects, each one identifying an
+ * interface that will be implemented by the returned proxy
+ * class
+ * @return a proxy class that implements all of the interfaces referred to
+ * in the contents of {@code interfaces}
+ * @throws IllegalArgumentException
+ * if any of the interface restrictions are violated
+ * @throws NullPointerException
+ * if either {@code interfaces} or any of its elements are
+ * {@code null}
+ */
+ public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
+ throws IllegalArgumentException {
+ if (loader == null) {
+ loader = ClassLoader.getSystemClassLoader();
+ }
+
+ if (interfaces == null) {
+ throw new NullPointerException("interfaces == null");
+ }
+
+ Set<Class<?>> interfacesSet = new CopyOnWriteArraySet<Class<?>>(Arrays.asList(interfaces));
+
+ Class<?> proxy = loader.proxyCache.get(interfacesSet);
+ if (proxy != null) {
+ return proxy;
+ }
+
+ if (interfacesSet.size() != interfaces.length) {
+ throw new IllegalArgumentException(
+ "interfaces has duplicates: " + Arrays.toString(interfaces));
+ }
+ String commonPackageName = null;
+ for (Class<?> c : interfaces) {
+ if (c == null) {
+ throw new NullPointerException("interfaces contained a null element");
+ }
+ if (!c.isInterface()) {
+ throw new IllegalArgumentException(c + " is not an interface");
+ }
+ if (!isVisibleToClassLoader(loader, c)) {
+ throw new IllegalArgumentException(c + " is not visible from class loader");
+ }
+ if (!Modifier.isPublic(c.getModifiers())) {
+ String packageName = c.getPackageName$();
+ if (packageName == null) {
+ packageName = "";
+ }
+ if (commonPackageName != null && !commonPackageName.equals(packageName)) {
+ throw new IllegalArgumentException(
+ "non-public interfaces must be in the same package");
+ }
+ commonPackageName = packageName;
+ }
+ }
+
+ String baseName = commonPackageName != null && !commonPackageName.isEmpty()
+ ? commonPackageName + ".$Proxy"
+ : "$Proxy";
+ String name = baseName + NextClassNameIndex++;
+
+ List<Method> methods = getMethods(interfaces);
+ Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
+ validateReturnTypes(methods);
+ List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
+
+ ArtMethod[] methodsArray = new ArtMethod[methods.size()];
+ for (int i = 0; i < methodsArray.length; i++) {
+ methodsArray[i] = methods.get(i).getArtMethod();
+ }
+ Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
+ Class<?> result = generateProxy(name, interfaces, loader, methodsArray, exceptionsArray);
+ loader.proxyCache.put(interfacesSet, result);
+ return result;
+ }
+
+ private static boolean isVisibleToClassLoader(ClassLoader loader, Class<?> c) {
+ try {
+ return loader == c.getClassLoader() || c == Class.forName(c.getName(), false, loader);
+ } catch (ClassNotFoundException ex) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns an instance of the dynamically built class for the specified
+ * interfaces. Method invocations on the returned instance are forwarded to
+ * the specified invocation handler. The interfaces must be visible from the
+ * supplied class loader; no duplicates are permitted. All non-public
+ * interfaces must be defined in the same package.
+ *
+ * @param loader
+ * the class loader that will define the proxy class
+ * @param interfaces
+ * an array of {@code Class} objects, each one identifying an
+ * interface that will be implemented by the returned proxy
+ * object
+ * @param invocationHandler
+ * the invocation handler that handles the dispatched method
+ * invocations
+ * @return a new proxy object that delegates to the handler {@code h}
+ * @throws IllegalArgumentException
+ * if any of the interface restrictions are violated
+ * @throws NullPointerException
+ * if the interfaces or any of its elements are null
+ */
+ public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
+ InvocationHandler invocationHandler)
+ throws IllegalArgumentException {
+
+ if (invocationHandler == null) {
+ throw new NullPointerException("invocationHandler == null");
+ }
+ Exception cause;
+ try {
+ return getProxyClass(loader, interfaces)
+ .getConstructor(InvocationHandler.class)
+ .newInstance(invocationHandler);
+ } catch (NoSuchMethodException e) {
+ cause = e;
+ } catch (IllegalAccessException e) {
+ cause = e;
+ } catch (InstantiationException e) {
+ cause = e;
+ } catch (InvocationTargetException e) {
+ cause = e;
+ }
+ AssertionError error = new AssertionError();
+ error.initCause(cause);
+ throw error;
+ }
+
+ /**
+ * Indicates whether or not the specified class is a dynamically generated
+ * proxy class.
+ *
+ * @param cl
+ * the class
+ * @return {@code true} if the class is a proxy class, {@code false}
+ * otherwise
+ * @throws NullPointerException
+ * if the class is {@code null}
+ */
+ public static boolean isProxyClass(Class<?> cl) {
+ return cl.isProxy();
+ }
+
+ /**
+ * Returns the invocation handler of the specified proxy instance.
+ *
+ * @param proxy
+ * the proxy instance
+ * @return the invocation handler of the specified proxy instance
+ * @throws IllegalArgumentException
+ * if the supplied {@code proxy} is not a proxy object
+ */
+ public static InvocationHandler getInvocationHandler(Object proxy)
+ throws IllegalArgumentException {
+ // TODO: return false for subclasses of Proxy not created by generateProxy()
+ if (!(proxy instanceof Proxy)) {
+ throw new IllegalArgumentException("not a proxy instance");
+ }
+ return ((Proxy) proxy).h;
+ }
+
+ private static List<Method> getMethods(Class<?>[] interfaces) {
+ List<Method> result = new ArrayList<Method>();
+ try {
+ result.add(Object.class.getMethod("equals", Object.class));
+ result.add(Object.class.getMethod("hashCode", EmptyArray.CLASS));
+ result.add(Object.class.getMethod("toString", EmptyArray.CLASS));
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError();
+ }
+
+ getMethodsRecursive(interfaces, result);
+ return result;
+ }
+
+ /**
+ * Fills {@code proxiedMethods} with the methods of {@code interfaces} and
+ * the interfaces they extend. May contain duplicates.
+ */
+ private static void getMethodsRecursive(Class<?>[] interfaces, List<Method> methods) {
+ for (Class<?> i : interfaces) {
+ getMethodsRecursive(i.getInterfaces(), methods);
+ Collections.addAll(methods, i.getDeclaredMethods());
+ }
+ }
+
+ /**
+ * Throws if any two methods in {@code methods} have the same name and
+ * parameters but incompatible return types.
+ *
+ * @param methods the methods to find exceptions for, ordered by name and
+ * signature.
+ */
+ private static void validateReturnTypes(List<Method> methods) {
+ Method vs = null;
+ for (Method method : methods) {
+ if (vs == null || !vs.equalNameAndParameters(method)) {
+ vs = method; // this has a different name or parameters
+ continue;
+ }
+ Class<?> returnType = method.getReturnType();
+ Class<?> vsReturnType = vs.getReturnType();
+ if (returnType.isInterface() && vsReturnType.isInterface()) {
+ // all interfaces are mutually compatible
+ } else if (vsReturnType.isAssignableFrom(returnType)) {
+ vs = method; // the new return type is a subtype; use it instead
+ } else if (!returnType.isAssignableFrom(vsReturnType)) {
+ throw new IllegalArgumentException("proxied interface methods have incompatible "
+ + "return types:\n " + vs + "\n " + method);
+ }
+ }
+ }
+
+ /**
+ * Remove methods that have the same name, parameters and return type. This
+ * computes the exceptions of each method; this is the intersection of the
+ * exceptions of equivalent methods.
+ *
+ * @param methods the methods to find exceptions for, ordered by name and
+ * signature.
+ */
+ private static List<Class<?>[]> deduplicateAndGetExceptions(List<Method> methods) {
+ List<Class<?>[]> exceptions = new ArrayList<Class<?>[]>(methods.size());
+
+ for (int i = 0; i < methods.size(); ) {
+ Method method = methods.get(i);
+ Class<?>[] exceptionTypes = method.getExceptionTypes();
+
+ if (i > 0 && Method.ORDER_BY_SIGNATURE.compare(method, methods.get(i - 1)) == 0) {
+ exceptions.set(i - 1, intersectExceptions(exceptions.get(i - 1), exceptionTypes));
+ methods.remove(i);
+ } else {
+ exceptions.add(exceptionTypes);
+ i++;
+ }
+ }
+ return exceptions;
+ }
+
+ /**
+ * Returns the exceptions that are declared in both {@code aExceptions} and
+ * {@code bExceptions}. If an exception type in one array is a subtype of an
+ * exception from the other, the subtype is included in the intersection.
+ */
+ private static Class<?>[] intersectExceptions(Class<?>[] aExceptions, Class<?>[] bExceptions) {
+ if (aExceptions.length == 0 || bExceptions.length == 0) {
+ return EmptyArray.CLASS;
+ }
+ if (Arrays.equals(aExceptions, bExceptions)) {
+ return aExceptions;
+ }
+ Set<Class<?>> intersection = new HashSet<Class<?>>();
+ for (Class<?> a : aExceptions) {
+ for (Class<?> b : bExceptions) {
+ if (a.isAssignableFrom(b)) {
+ intersection.add(b);
+ } else if (b.isAssignableFrom(a)) {
+ intersection.add(a);
+ }
+ }
+ }
+ return intersection.toArray(new Class<?>[intersection.size()]);
+ }
+
+ private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
+ ClassLoader loader, ArtMethod[] methods,
+ Class<?>[][] exceptions);
+
+ /*
+ * The VM clones this method's descriptor when generating a proxy class.
+ * There is no implementation.
+ */
+ private static native void constructorPrototype(InvocationHandler h);
+
+ static Object invoke(Proxy proxy, ArtMethod method, Object[] args) throws Throwable {
+ InvocationHandler h = proxy.h;
+ return h.invoke(proxy, new Method(method), args);
+ }
+}
diff --git a/libart/src/main/java/sun/misc/Unsafe.java b/libart/src/main/java/sun/misc/Unsafe.java
new file mode 100644
index 0000000..0a4d8b2
--- /dev/null
+++ b/libart/src/main/java/sun/misc/Unsafe.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package sun.misc;
+
+import dalvik.system.VMStack;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * The package name notwithstanding, this class is the quasi-standard
+ * way for Java code to gain access to and use functionality which,
+ * when unsupervised, would allow one to break the pointer/type safety
+ * of Java.
+ */
+public final class Unsafe {
+ /** Traditional dalvik name. */
+ private static final Unsafe THE_ONE = new Unsafe();
+ /** Traditional RI name. */
+ private static final Unsafe theUnsafe = THE_ONE;
+
+ /**
+ * This class is only privately instantiable.
+ */
+ private Unsafe() {}
+
+ /**
+ * Gets the unique instance of this class. This is only allowed in
+ * very limited situations.
+ */
+ public static Unsafe getUnsafe() {
+ /*
+ * Only code on the bootclasspath is allowed to get at the
+ * Unsafe instance.
+ */
+ ClassLoader calling = VMStack.getCallingClassLoader();
+ if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
+ throw new SecurityException("Unsafe access denied");
+ }
+
+ return THE_ONE;
+ }
+
+ /**
+ * Gets the raw byte offset from the start of an object's memory to
+ * the memory used to store the indicated instance field.
+ *
+ * @param field non-null; the field in question, which must be an
+ * instance field
+ * @return the offset to the field
+ */
+ public long objectFieldOffset(Field field) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ throw new IllegalArgumentException("valid for instance fields only");
+ }
+ return field.getOffset();
+ }
+
+ /**
+ * Gets the offset from the start of an array object's memory to
+ * the memory used to store its initial (zeroeth) element.
+ *
+ * @param clazz non-null; class in question; must be an array class
+ * @return the offset to the initial element
+ */
+ public int arrayBaseOffset(Class clazz) {
+ Class<?> component = clazz.getComponentType();
+ if (component == null) {
+ throw new IllegalArgumentException("Valid for array classes only: " + clazz);
+ }
+ // TODO: make the following not specific to the object model.
+ int offset = 12;
+ if (component == long.class || component == double.class) {
+ offset += 4; // 4 bytes of padding.
+ }
+ return offset;
+ }
+
+ /**
+ * Gets the size of each element of the given array class.
+ *
+ * @param clazz non-null; class in question; must be an array class
+ * @return > 0; the size of each element of the array
+ */
+ public int arrayIndexScale(Class clazz) {
+ Class<?> component = clazz.getComponentType();
+ if (component == null) {
+ throw new IllegalArgumentException("Valid for array classes only: " + clazz);
+ }
+ // TODO: make the following not specific to the object model.
+ if (!component.isPrimitive()) {
+ return 4;
+ } else if (component == long.class || component == double.class) {
+ return 8;
+ } else if (component == int.class || component == float.class) {
+ return 4;
+ } else if (component == char.class || component == short.class) {
+ return 2;
+ } else {
+ // component == byte.class || component == boolean.class.
+ return 1;
+ }
+ }
+
+ /**
+ * Performs a compare-and-set operation on an <code>int</code>
+ * field within the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param expectedValue expected value of the field
+ * @param newValue new value to store in the field if the contents are
+ * as expected
+ * @return <code>true</code> if the new value was in fact stored, and
+ * <code>false</code> if not
+ */
+ public native boolean compareAndSwapInt(Object obj, long offset,
+ int expectedValue, int newValue);
+
+ /**
+ * Performs a compare-and-set operation on a <code>long</code>
+ * field within the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param expectedValue expected value of the field
+ * @param newValue new value to store in the field if the contents are
+ * as expected
+ * @return <code>true</code> if the new value was in fact stored, and
+ * <code>false</code> if not
+ */
+ public native boolean compareAndSwapLong(Object obj, long offset,
+ long expectedValue, long newValue);
+
+ /**
+ * Performs a compare-and-set operation on an <code>Object</code>
+ * field (that is, a reference field) within the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param expectedValue expected value of the field
+ * @param newValue new value to store in the field if the contents are
+ * as expected
+ * @return <code>true</code> if the new value was in fact stored, and
+ * <code>false</code> if not
+ */
+ public native boolean compareAndSwapObject(Object obj, long offset,
+ Object expectedValue, Object newValue);
+
+ /**
+ * Gets an <code>int</code> field from the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native int getIntVolatile(Object obj, long offset);
+
+ /**
+ * Stores an <code>int</code> field into the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putIntVolatile(Object obj, long offset, int newValue);
+
+ /**
+ * Gets a <code>long</code> field from the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native long getLongVolatile(Object obj, long offset);
+
+ /**
+ * Stores a <code>long</code> field into the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putLongVolatile(Object obj, long offset, long newValue);
+
+ /**
+ * Gets an <code>Object</code> field from the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native Object getObjectVolatile(Object obj, long offset);
+
+ /**
+ * Stores an <code>Object</code> field into the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putObjectVolatile(Object obj, long offset,
+ Object newValue);
+
+ /**
+ * Gets an <code>int</code> field from the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native int getInt(Object obj, long offset);
+
+ /**
+ * Stores an <code>int</code> field into the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putInt(Object obj, long offset, int newValue);
+
+ /**
+ * Lazy set an int field.
+ */
+ public native void putOrderedInt(Object obj, long offset, int newValue);
+
+ /**
+ * Gets a <code>long</code> field from the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native long getLong(Object obj, long offset);
+
+ /**
+ * Stores a <code>long</code> field into the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putLong(Object obj, long offset, long newValue);
+
+ /**
+ * Lazy set a long field.
+ */
+ public native void putOrderedLong(Object obj, long offset, long newValue);
+
+ /**
+ * Gets an <code>Object</code> field from the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native Object getObject(Object obj, long offset);
+
+ /**
+ * Stores an <code>Object</code> field into the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putObject(Object obj, long offset, Object newValue);
+
+ /**
+ * Lazy set an object field.
+ */
+ public native void putOrderedObject(Object obj, long offset,
+ Object newValue);
+
+ /**
+ * Parks the calling thread for the specified amount of time,
+ * unless the "permit" for the thread is already available (due to
+ * a previous call to {@link #unpark}. This method may also return
+ * spuriously (that is, without the thread being told to unpark
+ * and without the indicated amount of time elapsing).
+ *
+ * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+ * in-depth information of the behavior of this method.</p>
+ *
+ * @param absolute whether the given time value is absolute
+ * milliseconds-since-the-epoch (<code>true</code>) or relative
+ * nanoseconds-from-now (<code>false</code>)
+ * @param time the (absolute millis or relative nanos) time value
+ */
+ public void park(boolean absolute, long time) {
+ if (absolute) {
+ Thread.currentThread().parkUntil(time);
+ } else {
+ Thread.currentThread().parkFor(time);
+ }
+ }
+
+ /**
+ * Unparks the given object, which must be a {@link Thread}.
+ *
+ * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+ * in-depth information of the behavior of this method.</p>
+ *
+ * @param obj non-null; the object to unpark
+ */
+ public void unpark(Object obj) {
+ if (obj instanceof Thread) {
+ ((Thread) obj).unpark();
+ } else {
+ throw new IllegalArgumentException("valid for Threads only");
+ }
+ }
+
+ /**
+ * Allocates an instance of the given class without running the constructor.
+ * The class' <clinit> will be run, if necessary.
+ */
+ public native Object allocateInstance(Class<?> c);
+}
diff --git a/libdvm/src/main/java/dalvik/system/VMRuntime.java b/libdvm/src/main/java/dalvik/system/VMRuntime.java
index 71098be..e1b4a00 100644
--- a/libdvm/src/main/java/dalvik/system/VMRuntime.java
+++ b/libdvm/src/main/java/dalvik/system/VMRuntime.java
@@ -68,6 +68,11 @@
public native String vmVersion();
/**
+ * Returns the name of the shared library providing the VM implementation.
+ */
+ public native String vmLibrary();
+
+ /**
* Gets the current ideal heap utilization, represented as a number
* between zero and one. After a GC happens, the Dalvik heap may
* be resized so that (size of live objects) / (size of heap) is
@@ -117,7 +122,7 @@
/**
* This method exists for binary compatibility. It was part of a
- * heap sizing API which was removed in Honeycomb.
+ * heap sizing API which was removed in Android 3.0 (Honeycomb).
*/
@Deprecated
public long getMinimumHeapSize() {
@@ -126,7 +131,7 @@
/**
* This method exists for binary compatibility. It was part of a
- * heap sizing API which was removed in Honeycomb.
+ * heap sizing API which was removed in Android 3.0 (Honeycomb).
*/
@Deprecated
public long setMinimumHeapSize(long size) {
@@ -159,7 +164,7 @@
/**
* This method exists for binary compatibility. It was part of
- * the external allocation API which was removed in Honeycomb.
+ * the external allocation API which was removed in Android 3.0 (Honeycomb).
*/
@Deprecated
public boolean trackExternalAllocation(long size) {
@@ -168,14 +173,14 @@
/**
* This method exists for binary compatibility. It was part of
- * the external allocation API which was removed in Honeycomb.
+ * the external allocation API which was removed in Android 3.0 (Honeycomb).
*/
@Deprecated
public void trackExternalFree(long size) {}
/**
* This method exists for binary compatibility. It was part of
- * the external allocation API which was removed in Honeycomb.
+ * the external allocation API which was removed in Android 3.0 (Honeycomb).
*/
@Deprecated
public long getExternalBytesAllocated() {
@@ -217,4 +222,24 @@
* Returns true if either a Java debugger or native debugger is active.
*/
public native boolean isDebuggerActive();
+
+ /**
+ * Registers a native allocation so that the heap knows about it and performs GC as required.
+ * If the number of native allocated bytes exceeds the native allocation watermark, the
+ * function requests a concurrent GC. If the native bytes allocated exceeds a second higher
+ * watermark, it is determined that the application is registering native allocations at an
+ * unusually high rate and a GC is performed inside of the function to prevent memory usage
+ * from excessively increasing.
+ */
+ public native void registerNativeAllocation(int bytes);
+
+ /**
+ * Registers a native free by reducing the number of native bytes accounted for.
+ */
+ public native void registerNativeFree(int bytes);
+
+ /**
+ * Fill in dex caches with classes, fields, and methods that are already loaded.
+ */
+ public native void preloadDexCaches();
}
diff --git a/libdvm/src/main/java/java/lang/Class.java b/libdvm/src/main/java/java/lang/Class.java
index 2f26688..4b36f3c 100644
--- a/libdvm/src/main/java/java/lang/Class.java
+++ b/libdvm/src/main/java/java/lang/Class.java
@@ -54,12 +54,14 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
-import libcore.util.CollectionUtils;
-import libcore.util.EmptyArray;
import org.apache.harmony.kernel.vm.StringUtils;
import libcore.reflect.AnnotationAccess;
import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.InternalNames;
import libcore.reflect.Types;
+import libcore.util.BasicLruCache;
+import libcore.util.CollectionUtils;
+import libcore.util.EmptyArray;
/**
* The in-memory representation of a Java class. This representation serves as
@@ -121,12 +123,24 @@
private static final long serialVersionUID = 3206093459760846163L;
/**
+ * Class def index from dex file. An index of -1 indicates that there is no class definition,
+ * for example for an array type.
+ */
+ private transient int dexClassDefIndex;
+
+ /** The type index of this class within the dex file that defines it. */
+ private transient int dexTypeIndex;
+
+ /**
+ * Have we computed the type and class def indices? Volatile to avoid double check locking bugs.
+ */
+ private transient volatile boolean dexIndicesInitialized;
+
+ /**
* Lazily computed name of this class; always prefer calling getName().
*/
private transient String name;
- private transient int dexTypeIndex;
-
private Class() {
// Prevent this class to be instantiated, instance
// should be created by JVM only
@@ -138,44 +152,48 @@
*/
public native Dex getDex();
+ /** Lazily compute indices in to Dex */
+ private synchronized void computeDexIndices() {
+ if (!dexIndicesInitialized) {
+ Dex dex = getDex();
+ dexTypeIndex = dex.findTypeIndex(InternalNames.getInternalName(this));
+ if (dexTypeIndex < 0) {
+ dexTypeIndex = -1;
+ dexClassDefIndex = -1;
+ } else {
+ dexClassDefIndex = dex.findClassDefIndexFromTypeIndex(dexTypeIndex);
+ }
+ dexIndicesInitialized = true;
+ }
+ }
+
/**
- * The type index of this class in its own Dex, or 0 if it is unknown. If a
- * class is referenced by multiple Dex files, it will have a different type
- * index in each. Dex files support 65534 type indices, with 65535
- * representing no index.
- *
- * TODO: 0 is a valid index; this should be -1 if it is unknown
+ * The class def of this class in its own Dex, or -1 if there is no class def.
*
* @hide
*/
- public int getTypeIndex() {
- int result = dexTypeIndex;
- if (result == 0) { // uncomputed => Dalvik
- result = AnnotationAccess.computeTypeIndex(getDex(), this);
- dexTypeIndex = result;
+ public int getDexClassDefIndex() {
+ if (!dexIndicesInitialized) {
+ computeDexIndices();
}
- return result;
+ return dexClassDefIndex;
}
/**
- * Get the Signature attribute for this class. Returns null if not found.
+ * The type index of this class in its own Dex, or -1 if it is unknown. If a class is referenced
+ * by multiple Dex files, it will have a different type index in each. Dex files support 65534
+ * type indices, with 65535 representing no index.
+ *
+ * @hide
*/
- private String getSignatureAttribute() {
- Object[] annotation = getSignatureAnnotation();
-
- if (annotation == null) {
- return null;
+ public int getDexTypeIndex() {
+ if (!dexIndicesInitialized) {
+ computeDexIndices();
}
-
- return StringUtils.combineStrings(annotation);
+ return dexTypeIndex;
}
/**
- * Get the Signature annotation for this class. Returns null if not found.
- */
- native private Object[] getSignatureAnnotation();
-
- /**
* Returns a {@code Class} object which represents the class with the
* given name. The name should be the name of a non-primitive class, as described in
* the {@link Class class definition}.
@@ -779,9 +797,22 @@
* void} then an empty array is returned.
*/
public Type[] getGenericInterfaces() {
- GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
- parser.parseForClass(this, getSignatureAttribute());
- return Types.getClonedTypeArray(parser.interfaceTypes);
+ Type[] result;
+ synchronized (Caches.genericInterfaces) {
+ result = Caches.genericInterfaces.get(this);
+ if (result == null) {
+ String annotationSignature = AnnotationAccess.getSignature(this);
+ if (annotationSignature == null) {
+ result = getInterfaces();
+ } else {
+ GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
+ parser.parseForClass(this, annotationSignature);
+ result = Types.getTypeArray(parser.interfaceTypes, false);
+ }
+ Caches.genericInterfaces.put(this, result);
+ }
+ }
+ return (result.length == 0) ? result : result.clone();
}
/**
@@ -789,9 +820,14 @@
* class}.
*/
public Type getGenericSuperclass() {
- GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
- parser.parseForClass(this, getSignatureAttribute());
- return Types.getType(parser.superclassType);
+ Type genericSuperclass = getSuperclass();
+ String annotationSignature = AnnotationAccess.getSignature(this);
+ if (annotationSignature != null) {
+ GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
+ parser.parseForClass(this, annotationSignature);
+ genericSuperclass = parser.superclassType;
+ }
+ return Types.getType(genericSuperclass);
}
/**
@@ -1031,9 +1067,13 @@
*/
@SuppressWarnings("unchecked")
public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
+ String annotationSignature = AnnotationAccess.getSignature(this);
+ if (annotationSignature == null) {
+ return EmptyArray.TYPE_VARIABLE;
+ }
GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
- parser.parseForClass(this, getSignatureAttribute());
- return parser.formalTypeParameters.clone();
+ parser.parseForClass(this, annotationSignature);
+ return parser.formalTypeParameters;
}
/**
@@ -1095,7 +1135,11 @@
* {@code enum}.
*/
public boolean isEnum() {
- return ((getModifiers() & 0x4000) != 0) && (getSuperclass() == Enum.class);
+ if (getSuperclass() != Enum.class) {
+ return false;
+ }
+ int mod = getModifiers(this, true);
+ return (mod & 0x4000) != 0;
}
/**
@@ -1170,9 +1214,8 @@
public String toString() {
if (isPrimitive()) {
return getSimpleName();
- } else {
- return (isInterface() ? "interface " : "class ") + getName();
}
+ return (isInterface() ? "interface " : "class ") + getName();
}
/**
@@ -1258,8 +1301,48 @@
*
* @hide
*/
- public int getAnnotationDirectoryOffset() {
- return AnnotationAccess.typeIndexToAnnotationDirectoryOffset(getDex(), getTypeIndex());
+ public int getDexAnnotationDirectoryOffset() {
+ Dex dex = getDex();
+ if (dex == null) {
+ return 0;
+ }
+ int classDefIndex = getDexClassDefIndex();
+ if (classDefIndex < 0) {
+ return 0;
+ }
+ return dex.annotationDirectoryOffsetFromClassDefIndex(classDefIndex);
}
+
+ /**
+ * Returns a resolved type from the dex cache, computing the type from the dex file if
+ * necessary.
+ * TODO: use Dalvik's dex cache.
+ * @hide
+ */
+ public Class<?> getDexCacheType(Dex dex, int typeIndex) {
+ String internalName = dex.typeNames().get(typeIndex);
+ return InternalNames.getClass(getClassLoader(), internalName);
+ }
+
+ /**
+ * Returns a string from the dex cache, computing the string from the dex file if necessary.
+ *
+ * @hide
+ */
+ public String getDexCacheString(Dex dex, int dexStringIndex) {
+ return dex.strings().get(dexStringIndex);
+ }
+
+
+ private static class Caches {
+ /**
+ * Cache to avoid frequent recalculation of generic interfaces, which is generally uncommon.
+ * Sized sufficient to allow ConcurrentHashMapTest to run without recalculating its generic
+ * interfaces (required to avoid time outs). Validated by running reflection heavy code
+ * such as applications using Guice-like frameworks.
+ */
+ private static final BasicLruCache<Class, Type[]> genericInterfaces
+ = new BasicLruCache<Class, Type[]>(8);
+ }
}
diff --git a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
index 9c6b8c7..f3d96af 100644
--- a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
+++ b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
@@ -54,7 +54,9 @@
*/
public class AccessibleObject implements AnnotatedElement {
- // If true, object is accessible, bypassing normal access checks
+ /**
+ * If true, object is accessible, bypassing normal access checks
+ */
boolean flag = false;
// Holds a mapping from Java type names to native type codes.
@@ -87,10 +89,8 @@
* @see #setAccessible(boolean)
*/
public static void setAccessible(AccessibleObject[] objects, boolean flag) {
- synchronized(AccessibleObject.class) {
- for (AccessibleObject object : objects) {
- object.flag = flag;
- }
+ for (AccessibleObject object : objects) {
+ object.flag = flag;
}
}
diff --git a/libdvm/src/main/java/java/lang/reflect/Constructor.java b/libdvm/src/main/java/java/lang/reflect/Constructor.java
index 531f269..ab417d2 100644
--- a/libdvm/src/main/java/java/lang/reflect/Constructor.java
+++ b/libdvm/src/main/java/java/lang/reflect/Constructor.java
@@ -153,12 +153,10 @@
appendTypeName(sb, getDeclaringClass());
// append parameters
sb.append('(');
- appendArrayGenericType(sb,
- Types.getClonedTypeArray(genericParameterTypes));
+ appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false));
sb.append(')');
// append exceptions if any
- Type[] genericExceptionTypeArray =
- Types.getClonedTypeArray(genericExceptionTypes);
+ Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false);
if (genericExceptionTypeArray.length > 0) {
sb.append(" throws ");
appendArrayGenericType(sb, genericExceptionTypeArray);
@@ -183,7 +181,7 @@
*/
public Type[] getGenericParameterTypes() {
initGenericTypes();
- return Types.getClonedTypeArray(genericParameterTypes);
+ return Types.getTypeArray(genericParameterTypes, true);
}
/**
@@ -203,7 +201,7 @@
*/
public Type[] getGenericExceptionTypes() {
initGenericTypes();
- return Types.getClonedTypeArray(genericExceptionTypes);
+ return Types.getTypeArray(genericExceptionTypes, true);
}
@Override
diff --git a/libdvm/src/main/java/java/lang/reflect/Method.java b/libdvm/src/main/java/java/lang/reflect/Method.java
index 028b9ca..f8efbf4 100644
--- a/libdvm/src/main/java/java/lang/reflect/Method.java
+++ b/libdvm/src/main/java/java/lang/reflect/Method.java
@@ -185,12 +185,10 @@
sb.append(".").append(getName());
// append parameters
sb.append('(');
- appendArrayGenericType(sb,
- Types.getClonedTypeArray(genericParameterTypes));
+ appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false));
sb.append(')');
// append exceptions if any
- Type[] genericExceptionTypeArray = Types.getClonedTypeArray(
- genericExceptionTypes);
+ Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false);
if (genericExceptionTypeArray.length > 0) {
sb.append(" throws ");
appendArrayGenericType(sb, genericExceptionTypeArray);
@@ -215,7 +213,7 @@
*/
public Type[] getGenericParameterTypes() {
initGenericTypes();
- return Types.getClonedTypeArray(genericParameterTypes);
+ return Types.getTypeArray(genericParameterTypes, true);
}
/**
@@ -234,7 +232,7 @@
*/
public Type[] getGenericExceptionTypes() {
initGenericTypes();
- return Types.getClonedTypeArray(genericExceptionTypes);
+ return Types.getTypeArray(genericExceptionTypes, true);
}
/**
diff --git a/luni/src/main/files/cacerts/02b73561.0 b/luni/src/main/files/cacerts/02b73561.0
new file mode 100644
index 0000000..573528b
--- /dev/null
+++ b/luni/src/main/files/cacerts/02b73561.0
@@ -0,0 +1,90 @@
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp
+ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow
+fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV
+BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM
+cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S
+HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996
+CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk
+3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz
+6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV
+HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
+EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv
+Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw
+Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww
+DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0
+5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
+Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI
+gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ
+aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl
+izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Secure Certificate Services
+ Validity
+ Not Before: Jan 1 00:00:00 2004 GMT
+ Not After : Dec 31 23:59:59 2028 GMT
+ Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Secure Certificate Services
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c0:71:33:82:8a:d0:70:eb:73:87:82:40:d5:1d:
+ e4:cb:c9:0e:42:90:f9:de:34:b9:a1:ba:11:f4:25:
+ 85:f3:cc:72:6d:f2:7b:97:6b:b3:07:f1:77:24:91:
+ 5f:25:8f:f6:74:3d:e4:80:c2:f8:3c:0d:f3:bf:40:
+ ea:f7:c8:52:d1:72:6f:ef:c8:ab:41:b8:6e:2e:17:
+ 2a:95:69:0c:cd:d2:1e:94:7b:2d:94:1d:aa:75:d7:
+ b3:98:cb:ac:bc:64:53:40:bc:8f:ac:ac:36:cb:5c:
+ ad:bb:dd:e0:94:17:ec:d1:5c:d0:bf:ef:a5:95:c9:
+ 90:c5:b0:ac:fb:1b:43:df:7a:08:5d:b7:b8:f2:40:
+ 1b:2b:27:9e:50:ce:5e:65:82:88:8c:5e:d3:4e:0c:
+ 7a:ea:08:91:b6:36:aa:2b:42:fb:ea:c2:a3:39:e5:
+ db:26:38:ad:8b:0a:ee:19:63:c7:1c:24:df:03:78:
+ da:e6:ea:c1:47:1a:0b:0b:46:09:dd:02:fc:de:cb:
+ 87:5f:d7:30:63:68:a1:ae:dc:32:a1:ba:be:fe:44:
+ ab:68:b6:a5:17:15:fd:bd:d5:a7:a7:9a:e4:44:33:
+ e9:88:8e:fc:ed:51:eb:93:71:4e:ad:01:e7:44:8e:
+ ab:2d:cb:a8:fe:01:49:48:f0:c0:dd:c7:68:d8:92:
+ fe:3d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 3C:D8:93:88:C2:C0:82:09:CC:01:99:06:93:20:E9:9E:70:09:63:4F
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/SecureCertificateServices.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/SecureCertificateServices.crl
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 87:01:6d:23:1d:7e:5b:17:7d:c1:61:32:cf:8f:e7:f3:8a:94:
+ 59:66:e0:9e:28:a8:5e:d3:b7:f4:34:e6:aa:39:b2:97:16:c5:
+ 82:6f:32:a4:e9:8c:e7:af:fd:ef:c2:e8:b9:4b:aa:a3:f4:e6:
+ da:8d:65:21:fb:ba:80:eb:26:28:85:1a:fe:39:8c:de:5b:04:
+ 04:b4:54:f9:a3:67:9e:41:fa:09:52:cc:05:48:a8:c9:3f:21:
+ 04:1e:ce:48:6b:fc:85:e8:c2:7b:af:7f:b7:cc:f8:5f:3a:fd:
+ 35:c6:0d:ef:97:dc:4c:ab:11:e1:6b:cb:31:d1:6c:fb:48:80:
+ ab:dc:9c:37:b8:21:14:4b:0d:71:3d:ec:83:33:6e:d1:6e:32:
+ 16:ec:98:c7:16:8b:59:a6:34:ab:05:57:2d:93:f7:aa:13:cb:
+ d2:13:e2:b7:2e:3b:cd:6b:50:17:09:68:3e:b5:26:57:ee:b6:
+ e0:b6:dd:b9:29:80:79:7d:8f:a3:f0:a4:28:a4:15:c4:85:f4:
+ 27:d4:6b:bf:e5:5c:e4:65:02:76:54:b4:e3:37:66:24:d3:19:
+ 61:c8:52:10:e5:8b:37:9a:b9:a9:f9:1d:bf:ea:99:92:61:96:
+ ff:01:cd:a1:5f:0d:bc:71:bc:0e:ac:0b:1d:47:45:1d:c1:ec:
+ 7c:ec:fd:29
+SHA1 Fingerprint=4A:65:D5:F4:1D:EF:39:B8:B8:90:4A:4A:D3:64:81:33:CF:C7:A1:D1
diff --git a/luni/src/main/files/cacerts/03e16f6c.0 b/luni/src/main/files/cacerts/03e16f6c.0
deleted file mode 100644
index f5ea442..0000000
--- a/luni/src/main/files/cacerts/03e16f6c.0
+++ /dev/null
@@ -1,78 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEEjCCAvqgAwIBAgIPAMEAizw8iBHRPvZj7N9AMA0GCSqGSIb3DQEBBAUAMHAx
-KzApBgNVBAsTIkNvcHlyaWdodCAoYykgMTk5NyBNaWNyb3NvZnQgQ29ycC4xHjAc
-BgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMYTWljcm9zb2Z0
-IFJvb3QgQXV0aG9yaXR5MB4XDTk3MDExMDA3MDAwMFoXDTIwMTIzMTA3MDAwMFow
-cDErMCkGA1UECxMiQ29weXJpZ2h0IChjKSAxOTk3IE1pY3Jvc29mdCBDb3JwLjEe
-MBwGA1UECxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3Nv
-ZnQgUm9vdCBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQCpAr3BcOY78k4bKJ+XeF4w6qKpjSVf+P6VTKO3/p2iID58UaKboo9gMmvRQmR5
-7qx2yVTa8uuchhyPn4Rms8VremIj1h083g8BkuiWxL8tZpqaaCaZ0Dosvwy1WCbB
-RucKPjiWLKkoOajsSYNC44QPu5psVWGsgnyhYC13TOmZtGQ7mlAcMQgkFJ+p55Er
-GOY9mGMUYFgFZZ8dN1KH96fvlALGG9O/VUWziYC/OuxUlE6u/ad6bXROrxjMlgko
-IQBXkGBpN7tLEgc8Vv9b+6RmCgim0oFWV++2O14WgXcE2va+roCV/rDNf9anGnJc
-PMq88AijIjCzBoXJsyB3E4XfAgMBAAGjgagwgaUwgaIGA1UdAQSBmjCBl4AQW9Bw
-72lyniNRfhSyTY7/y6FyMHAxKzApBgNVBAsTIkNvcHlyaWdodCAoYykgMTk5NyBN
-aWNyb3NvZnQgQ29ycC4xHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEh
-MB8GA1UEAxMYTWljcm9zb2Z0IFJvb3QgQXV0aG9yaXR5gg8AwQCLPDyIEdE+9mPs
-30AwDQYJKoZIhvcNAQEEBQADggEBAJXoC8CN85cYNe24ASTYdxHzXGAyn54Lyz4F
-kYiPyTrmIfLwV5MstaBHyGLv/NfMOztaqTZUaf4kbT/JzKreBXzdMY09nxBwarv+
-Ek8YacD80EPjEVogT+pie6+qGcgrNyUtvmWhEoolD2Oj91Qc+SHJ1hXzUqxuQzIH
-/YIX+OVnbA1R9r3xUse958Qw/CAxCYgdlSkaTdUdAqXxgOADtFv0sd3IV+5lScdS
-VLa0AygS/5DW8AiPfriXxas3LOR65Kh343agANBqP8HSNorgQRKoNWobats14dQc
-BOSoRQTIWjM4bk0cDWK3CqKM09VUP0bNHFWmcNsSOoeTdZ+n0qA=
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number:
- c1:00:8b:3c:3c:88:11:d1:3e:f6:63:ec:df:40
- Signature Algorithm: md5WithRSAEncryption
- Issuer: OU=Copyright (c) 1997 Microsoft Corp., OU=Microsoft Corporation, CN=Microsoft Root Authority
- Validity
- Not Before: Jan 10 07:00:00 1997 GMT
- Not After : Dec 31 07:00:00 2020 GMT
- Subject: OU=Copyright (c) 1997 Microsoft Corp., OU=Microsoft Corporation, CN=Microsoft Root Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:a9:02:bd:c1:70:e6:3b:f2:4e:1b:28:9f:97:78:
- 5e:30:ea:a2:a9:8d:25:5f:f8:fe:95:4c:a3:b7:fe:
- 9d:a2:20:3e:7c:51:a2:9b:a2:8f:60:32:6b:d1:42:
- 64:79:ee:ac:76:c9:54:da:f2:eb:9c:86:1c:8f:9f:
- 84:66:b3:c5:6b:7a:62:23:d6:1d:3c:de:0f:01:92:
- e8:96:c4:bf:2d:66:9a:9a:68:26:99:d0:3a:2c:bf:
- 0c:b5:58:26:c1:46:e7:0a:3e:38:96:2c:a9:28:39:
- a8:ec:49:83:42:e3:84:0f:bb:9a:6c:55:61:ac:82:
- 7c:a1:60:2d:77:4c:e9:99:b4:64:3b:9a:50:1c:31:
- 08:24:14:9f:a9:e7:91:2b:18:e6:3d:98:63:14:60:
- 58:05:65:9f:1d:37:52:87:f7:a7:ef:94:02:c6:1b:
- d3:bf:55:45:b3:89:80:bf:3a:ec:54:94:4e:ae:fd:
- a7:7a:6d:74:4e:af:18:cc:96:09:28:21:00:57:90:
- 60:69:37:bb:4b:12:07:3c:56:ff:5b:fb:a4:66:0a:
- 08:a6:d2:81:56:57:ef:b6:3b:5e:16:81:77:04:da:
- f6:be:ae:80:95:fe:b0:cd:7f:d6:a7:1a:72:5c:3c:
- ca:bc:f0:08:a3:22:30:b3:06:85:c9:b3:20:77:13:
- 85:df
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- 2.5.29.1:
- 0....[.p.ir.#Q~..M....r0p1+0)..U..."Copyright (c) 1997 Microsoft Corp.1.0...U....Microsoft Corporation1!0...U....Microsoft Root Authority......<<...>.c..@
- Signature Algorithm: md5WithRSAEncryption
- 95:e8:0b:c0:8d:f3:97:18:35:ed:b8:01:24:d8:77:11:f3:5c:
- 60:32:9f:9e:0b:cb:3e:05:91:88:8f:c9:3a:e6:21:f2:f0:57:
- 93:2c:b5:a0:47:c8:62:ef:fc:d7:cc:3b:3b:5a:a9:36:54:69:
- fe:24:6d:3f:c9:cc:aa:de:05:7c:dd:31:8d:3d:9f:10:70:6a:
- bb:fe:12:4f:18:69:c0:fc:d0:43:e3:11:5a:20:4f:ea:62:7b:
- af:aa:19:c8:2b:37:25:2d:be:65:a1:12:8a:25:0f:63:a3:f7:
- 54:1c:f9:21:c9:d6:15:f3:52:ac:6e:43:32:07:fd:82:17:f8:
- e5:67:6c:0d:51:f6:bd:f1:52:c7:bd:e7:c4:30:fc:20:31:09:
- 88:1d:95:29:1a:4d:d5:1d:02:a5:f1:80:e0:03:b4:5b:f4:b1:
- dd:c8:57:ee:65:49:c7:52:54:b6:b4:03:28:12:ff:90:d6:f0:
- 08:8f:7e:b8:97:c5:ab:37:2c:e4:7a:e4:a8:77:e3:76:a0:00:
- d0:6a:3f:c1:d2:36:8a:e0:41:12:a8:35:6a:1b:6a:db:35:e1:
- d4:1c:04:e4:a8:45:04:c8:5a:33:38:6e:4d:1c:0d:62:b7:0a:
- a2:8c:d3:d5:54:3f:46:cd:1c:55:a6:70:db:12:3a:87:93:75:
- 9f:a7:d2:a0
-SHA1 Fingerprint=A4:34:89:15:9A:52:0F:0D:93:D0:32:CC:AF:37:E7:FE:20:A8:B4:19
diff --git a/luni/src/main/files/cacerts/052e396b.0 b/luni/src/main/files/cacerts/052e396b.0
new file mode 100644
index 0000000..009c813
--- /dev/null
+++ b/luni/src/main/files/cacerts/052e396b.0
@@ -0,0 +1,87 @@
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1
+MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK
+EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh
+BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq
+xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G
+87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i
+2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U
+WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1
+0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G
+A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr
+pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL
+ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm
+aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv
+hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm
+hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
+dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3
+P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y
+iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no
+xqE=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Qualified CA Root
+ Validity
+ Not Before: May 30 10:44:50 2000 GMT
+ Not After : May 30 10:44:50 2020 GMT
+ Subject: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Qualified CA Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:e4:1e:9a:fe:dc:09:5a:87:a4:9f:47:be:11:5f:
+ af:84:34:db:62:3c:79:78:b7:e9:30:b5:ec:0c:1c:
+ 2a:c4:16:ff:e0:ec:71:eb:8a:f5:11:6e:ed:4f:0d:
+ 91:d2:12:18:2d:49:15:01:c2:a4:22:13:c7:11:64:
+ ff:22:12:9a:b9:8e:5c:2f:08:cf:71:6a:b3:67:01:
+ 59:f1:5d:46:f3:b0:78:a5:f6:0e:42:7a:e3:7f:1b:
+ cc:d0:f0:b7:28:fd:2a:ea:9e:b3:b0:b9:04:aa:fd:
+ f6:c7:b4:b1:b8:2a:a0:fb:58:f1:19:a0:6f:70:25:
+ 7e:3e:69:4a:7f:0f:22:d8:ef:ad:08:11:9a:29:99:
+ e1:aa:44:45:9a:12:5e:3e:9d:6d:52:fc:e7:a0:3d:
+ 68:2f:f0:4b:70:7c:13:38:ad:bc:15:25:f1:d6:ce:
+ ab:a2:c0:31:d6:2f:9f:e0:ff:14:59:fc:84:93:d9:
+ 87:7c:4c:54:13:eb:9f:d1:2d:11:f8:18:3a:3a:de:
+ 25:d9:f7:d3:40:ed:a4:06:12:c4:3b:e1:91:c1:56:
+ 35:f0:14:dc:65:36:09:6e:ab:a4:07:c7:35:d1:c2:
+ 03:33:36:5b:75:26:6d:42:f1:12:6b:43:6f:4b:71:
+ 94:fa:34:1d:ed:13:6e:ca:80:7f:98:2f:6c:b9:65:
+ d8:e9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 39:95:8B:62:8B:5C:C9:D4:80:BA:58:0F:97:3F:15:08:43:CC:98:A7
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:39:95:8B:62:8B:5C:C9:D4:80:BA:58:0F:97:3F:15:08:43:CC:98:A7
+ DirName:/C=SE/O=AddTrust AB/OU=AddTrust TTP Network/CN=AddTrust Qualified CA Root
+ serial:01
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 19:ab:75:ea:f8:8b:65:61:95:13:ba:69:04:ef:86:ca:13:a0:
+ c7:aa:4f:64:1b:3f:18:f6:a8:2d:2c:55:8f:05:b7:30:ea:42:
+ 6a:1d:c0:25:51:2d:a7:bf:0c:b3:ed:ef:08:7f:6c:3c:46:1a:
+ ea:18:43:df:76:cc:f9:66:86:9c:2c:68:f5:e9:17:f8:31:b3:
+ 18:c4:d6:48:7d:23:4c:68:c1:7e:bb:01:14:6f:c5:d9:6e:de:
+ bb:04:42:6a:f8:f6:5c:7d:e5:da:fa:87:eb:0d:35:52:67:d0:
+ 9e:97:76:05:93:3f:95:c7:01:e6:69:55:38:7f:10:61:99:c9:
+ e3:5f:a6:ca:3e:82:63:48:aa:e2:08:48:3e:aa:f2:b2:85:62:
+ a6:b4:a7:d9:bd:37:9c:68:b5:2d:56:7d:b0:b7:3f:a0:b1:07:
+ d6:e9:4f:dc:de:45:71:30:32:7f:1b:2e:09:f9:bf:52:a1:ee:
+ c2:80:3e:06:5c:2e:55:40:c1:1b:f5:70:45:b0:dc:5d:fa:f6:
+ 72:5a:77:d2:63:cd:cf:58:89:00:42:63:3f:79:39:d0:44:b0:
+ 82:6e:41:19:e8:dd:e0:c1:88:5a:d1:1e:71:93:1f:24:30:74:
+ e5:1e:a8:de:3c:27:37:7f:83:ae:9e:77:cf:f0:30:b1:ff:4b:
+ 99:e8:c6:a1
+SHA1 Fingerprint=4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF
diff --git a/luni/src/main/files/cacerts/1155c94b.0 b/luni/src/main/files/cacerts/1155c94b.0
deleted file mode 100644
index 5da96b6..0000000
--- a/luni/src/main/files/cacerts/1155c94b.0
+++ /dev/null
@@ -1,87 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx
-IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1
-dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
-MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w
-HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx
-IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1
-dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
-MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u
-Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY
-rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z
-hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay
-BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL
-iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb
-AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv
-bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0
-MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
-FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n
-VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq
-u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m
-hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl
-ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp
-QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5
-quGnM/b9Sh/22WA=
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=ES, L=C/ Muntaner 244 Barcelona, CN=Autoridad de Certificacion Firmaprofesional CIF A62634068/emailAddress=ca@firmaprofesional.com
- Validity
- Not Before: Oct 24 22:00:00 2001 GMT
- Not After : Oct 24 22:00:00 2013 GMT
- Subject: C=ES, L=C/ Muntaner 244 Barcelona, CN=Autoridad de Certificacion Firmaprofesional CIF A62634068/emailAddress=ca@firmaprofesional.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:e7:23:03:6f:6f:23:a5:5e:78:ce:95:2c:ed:94:
- 1e:6e:0a:9e:01:c7:ea:30:d1:2c:9d:dd:37:e8:9b:
- 98:79:56:d3:fc:73:df:d0:8a:de:55:8f:51:f9:5a:
- ea:de:b5:70:c4:ed:a4:ed:ff:a3:0d:6e:0f:64:50:
- 31:af:01:27:58:ae:fe:6c:a7:4a:2f:17:2d:d3:73:
- d5:13:1c:8f:59:a5:34:2c:1d:54:04:45:cd:68:b8:
- a0:c0:03:a5:cf:85:42:47:95:28:5b:cf:ef:80:6c:
- e0:90:97:8a:01:3c:1d:f3:87:10:30:26:48:7d:d7:
- fc:e9:9d:91:71:ff:41:9a:a9:40:b5:37:9c:29:20:
- 4f:1f:52:e3:a0:7d:13:6d:54:b7:0a:de:e9:6a:4e:
- 07:ac:ac:19:5f:dc:7e:62:74:f6:b2:05:00:ba:85:
- a0:fd:1d:38:6e:cb:5a:bb:86:bc:94:67:33:35:83:
- 2c:1f:23:cd:f8:c8:91:71:cc:97:8b:ef:ae:0f:dc:
- 29:03:1b:c0:39:eb:70:ed:c1:6e:0e:d8:67:0b:89:
- a9:bc:35:e4:ef:b6:34:b4:a5:b6:c4:2d:a5:be:d0:
- c3:94:24:48:db:df:96:d3:00:b5:66:1a:8b:66:05:
- 0f:dd:3f:3f:cb:3f:aa:5e:9a:4a:f8:b4:4a:ef:95:
- 37:1b
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Subject Alternative Name:
- URI:http://www.firmaprofesional.com
- X509v3 Basic Constraints: critical
- CA:TRUE, pathlen:1
- X509v3 Private Key Usage Period:
- Not Before: Oct 24 22:00:00 2001 GMT, Not After: Oct 24 22:00:00 2013 GMT
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- 33:0B:A0:66:D1:EA:DA:CE:DE:62:93:04:28:52:B5:14:7F:38:68:B7
- Signature Algorithm: sha1WithRSAEncryption
- 47:73:fe:8d:27:54:f0:f5:d4:77:9c:27:79:57:57:b7:15:56:
- ec:c7:d8:58:b7:01:02:f4:33:ed:93:50:88:9e:7c:46:b1:bd:
- 3f:14:6f:f1:b3:47:48:8b:8c:97:06:d7:ea:7e:a3:5c:2a:bb:
- 4d:2f:47:e2:f8:39:06:c9:9c:2e:31:1a:03:78:f4:bc:38:c6:
- 22:8b:33:31:f0:16:04:04:7d:f9:76:e4:4b:d7:c0:e6:83:ec:
- 59:cc:3f:de:ff:4f:6b:b7:67:7e:a6:86:81:32:23:03:9d:c8:
- f7:5f:c1:4a:60:a5:92:a9:b1:a4:a0:60:c3:78:87:b3:22:f3:
- 2a:eb:5b:a9:ed:05:ab:37:0f:b1:e2:d3:95:76:63:56:74:8c:
- 58:72:1b:37:e5:64:a1:be:4d:0c:93:98:0c:97:f6:87:6d:b3:
- 3f:e7:cb:80:a6:ed:88:c7:5f:50:62:02:e8:99:74:16:d0:e6:
- b4:39:f1:27:cb:c8:40:d6:e3:86:10:a9:23:12:92:e0:69:41:
- 63:a7:af:25:0b:c0:c5:92:cb:1e:98:a3:5a:ba:c5:33:0f:a0:
- 97:01:dd:7f:e0:7b:d6:06:54:cf:a1:e2:4d:38:eb:4b:50:b5:
- cb:26:f4:ca:da:70:4a:6a:a1:e2:79:aa:e1:a7:33:f6:fd:4a:
- 1f:f6:d9:60
-SHA1 Fingerprint=A9:62:8F:4B:98:A9:1B:48:35:BA:D2:C1:46:32:86:BB:66:64:6A:8C
diff --git a/luni/src/main/files/cacerts/11a09b38.0 b/luni/src/main/files/cacerts/11a09b38.0
deleted file mode 100644
index 535eb66..0000000
--- a/luni/src/main/files/cacerts/11a09b38.0
+++ /dev/null
@@ -1,112 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE
-SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw
-ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU
-REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr
-2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s
-2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU
-GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj
-dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r
-TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/
-BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB
-AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv
-c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl
-ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu
-MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg
-T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud
-HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD
-VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny
-bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy
-MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ
-J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG
-SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom
-JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO
-inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y
-caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB
-mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ
-YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9
-BKNDLdr8C2LqL19iUw==
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 1044954564 (0x3e48bdc4)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=DK, O=TDC, CN=TDC OCES CA
- Validity
- Not Before: Feb 11 08:39:30 2003 GMT
- Not After : Feb 11 09:09:30 2037 GMT
- Subject: C=DK, O=TDC, CN=TDC OCES CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:ac:62:f6:61:20:b2:cf:c0:c6:85:d7:e3:79:e6:
- cc:ed:f2:39:92:a4:97:2e:64:a3:84:5b:87:9c:4c:
- fd:a4:f3:c4:5f:21:bd:56:10:eb:db:2e:61:ec:93:
- 69:e3:a3:cc:bd:99:c3:05:fc:06:b8:ca:36:1c:fe:
- 90:8e:49:4c:c4:56:9a:2f:56:bc:cf:7b:0c:f1:6f:
- 47:a6:0d:43:4d:e2:e9:1d:39:34:cd:8d:2c:d9:12:
- 98:f9:e3:e1:c1:4a:7c:86:38:c4:a9:c4:61:88:d2:
- 5e:af:1a:26:4d:d5:e4:a0:22:47:84:d9:64:b7:19:
- 96:fc:ec:19:e4:b2:97:26:4e:4a:4c:cb:8f:24:8b:
- 54:18:1c:48:61:7b:d5:88:68:da:5d:b5:ea:cd:1a:
- 30:c1:80:83:76:50:aa:4f:d1:d4:dd:38:f0:ef:16:
- f4:e1:0c:50:06:bf:ea:fb:7a:49:a1:28:2b:1c:f6:
- fc:15:32:a3:74:6a:8f:a9:c3:62:29:71:31:e5:3b:
- a4:60:17:5e:74:e6:da:13:ed:e9:1f:1f:1b:d1:b2:
- 68:73:c6:10:34:75:46:10:10:e3:90:00:76:40:cb:
- 8b:b7:43:09:21:ff:ab:4e:93:c6:58:e9:a5:82:db:
- 77:c4:3a:99:b1:72:95:49:04:f0:b7:2b:fa:7b:59:
- 8e:dd
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Certificate Policies:
- Policy: 1.2.208.169.1.1.1
- CPS: http://www.certifikat.dk/repository
- User Notice:
- Organization: TDC
- Number: 1
- Explicit Text: Certifikater fra denne CA udstedes under OID 1.2.208.169.1.1.1. Certificates from this CA are issued under OID 1.2.208.169.1.1.1.
-
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
-
- Full Name:
- DirName: C = DK, O = TDC, CN = TDC OCES CA, CN = CRL1
-
- Full Name:
- URI:http://crl.oces.certifikat.dk/oces.crl
-
- X509v3 Private Key Usage Period:
- Not Before: Feb 11 08:39:30 2003 GMT, Not After: Feb 11 09:09:30 2037 GMT
- X509v3 Authority Key Identifier:
- keyid:60:B5:85:EC:56:64:7E:12:19:27:67:1D:50:15:4B:73:AE:3B:F9:12
-
- X509v3 Subject Key Identifier:
- 60:B5:85:EC:56:64:7E:12:19:27:67:1D:50:15:4B:73:AE:3B:F9:12
- 1.2.840.113533.7.65.0:
- 0...V6.0:4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 0a:ba:26:26:46:d3:73:a8:09:f3:6b:0b:30:99:fd:8a:e1:57:
- 7a:11:d3:b8:94:d7:09:10:6e:a3:b1:38:03:d1:b6:f2:43:41:
- 29:62:a7:72:d8:fb:7c:05:e6:31:70:27:54:18:4e:8a:7c:4e:
- e5:d1:ca:8c:78:88:cf:1b:d3:90:8b:e6:23:f8:0b:0e:33:43:
- 7d:9c:e2:0a:19:8f:c9:01:3e:74:5d:74:c9:8b:1c:03:e5:18:
- c8:01:4c:3f:cb:97:05:5d:98:71:a6:98:6f:b6:7c:bd:37:7f:
- be:e1:93:25:6d:6f:f0:0a:ad:17:18:e1:03:bc:07:29:c8:ad:
- 26:e8:f8:61:f0:fd:21:09:7e:9a:8e:a9:68:7d:48:62:72:bd:
- 00:ea:01:99:b8:06:82:51:81:4e:f1:f5:b4:91:54:b9:23:7a:
- 00:9a:9f:5d:8d:e0:3c:64:b9:1a:12:92:2a:c7:82:44:72:39:
- dc:e2:3c:c6:d8:55:f5:15:4e:c8:05:0e:db:c6:d0:62:a6:ec:
- 15:b4:b5:02:82:db:ac:8c:a2:81:f0:9b:99:31:f5:20:20:a8:
- 88:61:0a:07:9f:94:fc:d0:d7:1b:cc:2e:17:f3:04:27:76:67:
- eb:54:83:fd:a4:90:7e:06:3d:04:a3:43:2d:da:fc:0b:62:ea:
- 2f:5f:62:53
-SHA1 Fingerprint=87:81:C2:5A:96:BD:C2:FB:4C:65:06:4F:F9:39:0B:26:04:8A:0E:01
diff --git a/luni/src/main/files/cacerts/124bbd54.0 b/luni/src/main/files/cacerts/124bbd54.0
new file mode 100644
index 0000000..67e0675
--- /dev/null
+++ b/luni/src/main/files/cacerts/124bbd54.0
@@ -0,0 +1,90 @@
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0
+aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla
+MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
+BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD
+VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW
+fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt
+TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL
+fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW
+1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7
+kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G
+A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v
+ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo
+dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu
+Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/
+HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
+pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS
+jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+
+xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn
+dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Trusted Certificate Services
+ Validity
+ Not Before: Jan 1 00:00:00 2004 GMT
+ Not After : Dec 31 23:59:59 2028 GMT
+ Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Trusted Certificate Services
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:df:71:6f:36:58:53:5a:f2:36:54:57:80:c4:74:
+ 08:20:ed:18:7f:2a:1d:e6:35:9a:1e:25:ac:9c:e5:
+ 96:7e:72:52:a0:15:42:db:59:dd:64:7a:1a:d0:b8:
+ 7b:dd:39:15:bc:55:48:c4:ed:3a:00:ea:31:11:ba:
+ f2:71:74:1a:67:b8:cf:33:cc:a8:31:af:a3:e3:d7:
+ 7f:bf:33:2d:4c:6a:3c:ec:8b:c3:92:d2:53:77:24:
+ 74:9c:07:6e:70:fc:bd:0b:5b:76:ba:5f:f2:ff:d7:
+ 37:4b:4a:60:78:f7:f0:fa:ca:70:b4:ea:59:aa:a3:
+ ce:48:2f:a9:c3:b2:0b:7e:17:72:16:0c:a6:07:0c:
+ 1b:38:cf:c9:62:b7:3f:a0:93:a5:87:41:f2:b7:70:
+ 40:77:d8:be:14:7c:e3:a8:c0:7a:8e:e9:63:6a:d1:
+ 0f:9a:c6:d2:f4:8b:3a:14:04:56:d4:ed:b8:cc:6e:
+ f5:fb:e2:2c:58:bd:7f:4f:6b:2b:f7:60:24:58:24:
+ ce:26:ef:34:91:3a:d5:e3:81:d0:b2:f0:04:02:d7:
+ 5b:b7:3e:92:ac:6b:12:8a:f9:e4:05:b0:3b:91:49:
+ 5c:b2:eb:53:ea:f8:9f:47:86:ee:bf:95:c0:c0:06:
+ 9f:d2:5b:5e:11:1b:f4:c7:04:35:29:d2:55:5c:e4:
+ ed:eb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ C5:7B:58:BD:ED:DA:25:69:D2:F7:59:16:A8:B3:32:C0:7B:27:5B:F4
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/TrustedCertificateServices.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/TrustedCertificateServices.crl
+
+ Signature Algorithm: sha1WithRSAEncryption
+ c8:93:81:3b:89:b4:af:b8:84:12:4c:8d:d2:f0:db:70:ba:57:
+ 86:15:34:10:b9:2f:7f:1e:b0:a8:89:60:a1:8a:c2:77:0c:50:
+ 4a:9b:00:8b:d8:8b:f4:41:e2:d0:83:8a:4a:1c:14:06:b0:a3:
+ 68:05:70:31:30:a7:53:9b:0e:e9:4a:a0:58:69:67:0e:ae:9d:
+ f6:a5:2c:41:bf:3c:06:6b:e4:59:cc:6d:10:f1:96:6f:1f:df:
+ f4:04:02:a4:9f:45:3e:c8:d8:fa:36:46:44:50:3f:82:97:91:
+ 1f:28:db:18:11:8c:2a:e4:65:83:57:12:12:8c:17:3f:94:36:
+ fe:5d:b0:c0:04:77:13:b8:f4:15:d5:3f:38:cc:94:3a:55:d0:
+ ac:98:f5:ba:00:5f:e0:86:19:81:78:2f:28:c0:7e:d3:cc:42:
+ 0a:f5:ae:50:a0:d1:3e:c6:a1:71:ec:3f:a0:20:8c:66:3a:89:
+ b4:8e:d4:d8:b1:4d:25:47:ee:2f:88:c8:b5:e1:05:45:c0:be:
+ 14:71:de:7a:fd:8e:7b:7d:4d:08:96:a5:12:73:f0:2d:ca:37:
+ 27:74:12:27:4c:cb:b6:97:e9:d9:ae:08:6d:5a:39:40:dd:05:
+ 47:75:6a:5a:21:b3:a3:18:cf:4e:f7:2e:57:b7:98:70:5e:c8:
+ c4:78:b0:62
+SHA1 Fingerprint=E1:9F:E3:0E:8B:84:60:9E:80:9B:17:0D:72:A8:C5:BA:6E:14:09:BD
diff --git a/luni/src/main/files/cacerts/1676090a.0 b/luni/src/main/files/cacerts/1676090a.0
new file mode 100644
index 0000000..d8505a9
--- /dev/null
+++ b/luni/src/main/files/cacerts/1676090a.0
@@ -0,0 +1,84 @@
+-----BEGIN CERTIFICATE-----
+MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
+Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g
+Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0
+aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa
+Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg
+SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo
+aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp
+ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z
+7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//
+DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx
+zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8
+hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs
+4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u
+gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY
+NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
+FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3
+j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG
+52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB
+echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
+ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI
+zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy
+wy39FCqQmbkHzJ8=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1218379777 (0x489f0001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=CN, O=China Internet Network Information Center, CN=China Internet Network Information Center EV Certificates Root
+ Validity
+ Not Before: Aug 31 07:11:25 2010 GMT
+ Not After : Aug 31 07:11:25 2030 GMT
+ Subject: C=CN, O=China Internet Network Information Center, CN=China Internet Network Information Center EV Certificates Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:9b:7e:73:ee:bd:3b:78:aa:64:43:41:f5:50:df:
+ 94:f2:2e:b2:8d:4a:8e:46:54:d2:21:12:c8:39:32:
+ 42:06:e9:83:d5:9f:52:ed:e5:67:03:3b:54:c1:8c:
+ 99:99:cc:e9:c0:0f:ff:0d:d9:84:11:b2:b8:d1:cb:
+ 5b:dc:1e:f9:68:31:64:e1:9b:fa:74:eb:68:b9:20:
+ 95:f7:c6:0f:8d:47:ac:5a:06:dd:61:ab:e2:ec:d8:
+ 9f:17:2d:9c:ca:3c:35:97:55:71:cd:43:85:b1:47:
+ 16:f5:2c:53:80:76:cf:d3:00:64:bd:40:99:dd:cc:
+ d8:db:c4:9f:d6:13:5f:41:83:8b:f9:0d:87:92:56:
+ 34:6c:1a:10:0b:17:d5:5a:1c:97:58:84:3c:84:1a:
+ 2e:5c:91:34:6e:19:5f:7f:17:69:c5:65:ef:6b:21:
+ c6:d5:50:3a:bf:61:b9:05:8d:ef:6f:34:3a:b2:6f:
+ 14:63:bf:16:3b:9b:a9:2a:fd:b7:2b:38:66:06:c5:
+ 2c:e2:aa:67:1e:45:a7:8d:04:66:42:f6:8f:2b:ef:
+ 88:20:69:8f:32:8c:14:73:da:2b:86:91:63:22:9a:
+ f2:a7:db:ce:89:8b:ab:5d:c7:14:c1:5b:30:6a:1f:
+ b1:b7:9e:2e:81:01:02:ed:cf:96:5e:63:db:a8:e6:
+ 38:b7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:7C:72:4B:39:C7:C0:DB:62:A5:4F:9B:AA:18:34:92:A2:CA:83:82:59
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 7C:72:4B:39:C7:C0:DB:62:A5:4F:9B:AA:18:34:92:A2:CA:83:82:59
+ Signature Algorithm: sha1WithRSAEncryption
+ 2a:c3:c7:43:37:8f:dd:ad:a4:b2:0c:ee:dc:14:6d:8f:28:a4:
+ 98:49:cb:0c:80:ea:f3:ed:23:66:75:7d:c5:d3:21:67:79:d1:
+ 73:c5:b5:03:b7:58:ac:0c:54:2f:c6:56:13:0f:31:da:06:e7:
+ 65:3b:1d:6f:36:db:c8:1d:f9:fd:80:06:ca:a3:3d:66:16:a8:
+ 9d:4c:16:7d:c0:95:46:b5:51:e4:e2:1f:d7:ea:06:4d:63:8d:
+ 96:8c:ef:e7:33:57:42:3a:eb:8c:c1:79:c8:4d:76:7d:de:f6:
+ b1:b7:81:e0:a0:f9:a1:78:46:17:1a:56:98:f0:4e:3d:ab:1c:
+ ed:ec:39:dc:07:48:f7:63:fe:06:ae:c2:a4:5c:6a:5b:32:88:
+ c5:c7:33:85:ac:66:42:47:c2:58:24:99:e1:e5:3e:e5:75:2c:
+ 8e:43:d6:5d:3c:78:1e:a8:95:82:29:50:d1:d1:16:ba:ef:c1:
+ be:7a:d9:b4:d8:cc:1e:4c:46:e1:77:b1:31:ab:bd:2a:c8:ce:
+ 8f:6e:a1:5d:7f:03:75:34:e4:ad:89:45:54:5e:be:ae:28:a5:
+ bb:3f:78:79:eb:73:b3:0a:0d:fd:be:c9:f7:56:ac:f6:b7:ed:
+ 2f:9b:21:29:c7:38:b6:95:c4:04:f2:c3:2d:fd:14:2a:90:99:
+ b9:07:cc:9f
+SHA1 Fingerprint=4F:99:AA:93:FB:2B:D1:37:26:A1:99:4A:CE:7F:F0:05:F2:93:5D:1E
diff --git a/luni/src/main/files/cacerts/1920cacb.0 b/luni/src/main/files/cacerts/1920cacb.0
deleted file mode 100644
index 19fae29..0000000
--- a/luni/src/main/files/cacerts/1920cacb.0
+++ /dev/null
@@ -1,111 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGBzCCBO+gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBsjELMAkGA1UEBhMCRVMx
-DzANBgNVBAgTBk1hZHJpZDEPMA0GA1UEBxMGTWFkcmlkMS8wLQYDVQQKEyZJUFMg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgcy5sLiBpcHNDQTEOMAwGA1UECxMFaXBz
-Q0ExHTAbBgNVBAMTFGlwc0NBIEdsb2JhbCBDQSBSb290MSEwHwYJKoZIhvcNAQkB
-FhJnbG9iYWwwMUBpcHNjYS5jb20wHhcNMDkwOTA3MTQzODQ0WhcNMjkxMjI1MTQz
-ODQ0WjCBsjELMAkGA1UEBhMCRVMxDzANBgNVBAgTBk1hZHJpZDEPMA0GA1UEBxMG
-TWFkcmlkMS8wLQYDVQQKEyZJUFMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgcy5s
-LiBpcHNDQTEOMAwGA1UECxMFaXBzQ0ExHTAbBgNVBAMTFGlwc0NBIEdsb2JhbCBD
-QSBSb290MSEwHwYJKoZIhvcNAQkBFhJnbG9iYWwwMUBpcHNjYS5jb20wggEiMA0G
-CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCn78yAMLCRJE+waPjDyi0VOFVYguI4
-Y7D3o5Jvg7iwXrCMrFSxd9BQ4JezkK2Ksx85K0VW96ri33yy7G9TL5rL0OZmy8kT
-6HLitM0xV4cStZPo+nLO6kfyjLSwY9cEALdkNjmX6JXxiPlxDQMnjGHPCIOWT4PF
-Tuhc+AZw8QKqHB6pyKp+513NjTwUb2fQG6kjSIshKDqKTOYRMfkhLrJnZsYpbpST
-z0CW/LA9v7K0k79WcbalQYewWLVZIyhJuJj5UB4tFSgLTKxJ0YSpm5rnclS3ONDb
-yf6pc9VtEM2Odev+l/2APPy02Ej0mUYLiBSkti7bTGD0IcFsgJUU1a/VAgMBAAGj
-ggIkMIICIDAdBgNVHQ4EFgQUFaaWgLEVSzHDwpz25xMLS/MYzYYwgd8GA1UdIwSB
-1zCB1IAUFaaWgLEVSzHDwpz25xMLS/MYzYahgbikgbUwgbIxCzAJBgNVBAYTAkVT
-MQ8wDQYDVQQIEwZNYWRyaWQxDzANBgNVBAcTBk1hZHJpZDEvMC0GA1UEChMmSVBT
-IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IHMubC4gaXBzQ0ExDjAMBgNVBAsTBWlw
-c0NBMR0wGwYDVQQDExRpcHNDQSBHbG9iYWwgQ0EgUm9vdDEhMB8GCSqGSIb3DQEJ
-ARYSZ2xvYmFsMDFAaXBzY2EuY29tggEAMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQD
-AgEGMEcGA1UdJQRAMD4GCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsG
-AQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwoDBDAdBgNVHREEFjAUgRJnbG9iYWww
-MUBpcHNjYS5jb20wHQYDVR0SBBYwFIESZ2xvYmFsMDFAaXBzY2EuY29tMEEGA1Ud
-HwQ6MDgwNqA0oDKGMGh0dHA6Ly9jcmxnbG9iYWwwMS5pcHNjYS5jb20vY3JsL2Ny
-bGdsb2JhbDAxLmNybDA4BggrBgEFBQcBAQQsMCowKAYIKwYBBQUHMAGGHGh0dHA6
-Ly9jcmxnbG9iYWwwMS5pcHNjYS5jb20wDQYJKoZIhvcNAQEFBQADggEBABj0rv6A
-D47Bd2+iWkdInyNVoVNr+V2nMKUkvkMv+MHRV/k+LIAlzEapNvNJWx32fNdjs00+
-ePantAJ3+HkNPmrLGGC4/QCvDN1U41SPIj3zEG8RDbUeeo0nzAi4W8O4Gl8rp2A/
-ABz3D1xCZmSehxKAcIng+lcoDk4fEC/ZBYC2gC8cafD2tmU0BW/K2T741F03Mse4
-K8z/c5MAceAByKpDvanxzvqA+fFDEpGmZeVgB01HuisvBPZKhSmIZRDJslNinGyb
-YFwaG9OuxR1ymQb/BcyGJnO01FQF3R5rADu3iejjkQIgEuvv6f4KKSOBI6MA2nDM
-kl83I9AcezVcA3o=
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 0 (0x0)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=ES, ST=Madrid, L=Madrid, O=IPS Certification Authority s.l. ipsCA, OU=ipsCA, CN=ipsCA Global CA Root/emailAddress=global01@ipsca.com
- Validity
- Not Before: Sep 7 14:38:44 2009 GMT
- Not After : Dec 25 14:38:44 2029 GMT
- Subject: C=ES, ST=Madrid, L=Madrid, O=IPS Certification Authority s.l. ipsCA, OU=ipsCA, CN=ipsCA Global CA Root/emailAddress=global01@ipsca.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:a7:ef:cc:80:30:b0:91:24:4f:b0:68:f8:c3:ca:
- 2d:15:38:55:58:82:e2:38:63:b0:f7:a3:92:6f:83:
- b8:b0:5e:b0:8c:ac:54:b1:77:d0:50:e0:97:b3:90:
- ad:8a:b3:1f:39:2b:45:56:f7:aa:e2:df:7c:b2:ec:
- 6f:53:2f:9a:cb:d0:e6:66:cb:c9:13:e8:72:e2:b4:
- cd:31:57:87:12:b5:93:e8:fa:72:ce:ea:47:f2:8c:
- b4:b0:63:d7:04:00:b7:64:36:39:97:e8:95:f1:88:
- f9:71:0d:03:27:8c:61:cf:08:83:96:4f:83:c5:4e:
- e8:5c:f8:06:70:f1:02:aa:1c:1e:a9:c8:aa:7e:e7:
- 5d:cd:8d:3c:14:6f:67:d0:1b:a9:23:48:8b:21:28:
- 3a:8a:4c:e6:11:31:f9:21:2e:b2:67:66:c6:29:6e:
- 94:93:cf:40:96:fc:b0:3d:bf:b2:b4:93:bf:56:71:
- b6:a5:41:87:b0:58:b5:59:23:28:49:b8:98:f9:50:
- 1e:2d:15:28:0b:4c:ac:49:d1:84:a9:9b:9a:e7:72:
- 54:b7:38:d0:db:c9:fe:a9:73:d5:6d:10:cd:8e:75:
- eb:fe:97:fd:80:3c:fc:b4:d8:48:f4:99:46:0b:88:
- 14:a4:b6:2e:db:4c:60:f4:21:c1:6c:80:95:14:d5:
- af:d5
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Subject Key Identifier:
- 15:A6:96:80:B1:15:4B:31:C3:C2:9C:F6:E7:13:0B:4B:F3:18:CD:86
- X509v3 Authority Key Identifier:
- keyid:15:A6:96:80:B1:15:4B:31:C3:C2:9C:F6:E7:13:0B:4B:F3:18:CD:86
- DirName:/C=ES/ST=Madrid/L=Madrid/O=IPS Certification Authority s.l. ipsCA/OU=ipsCA/CN=ipsCA Global CA Root/emailAddress=global01@ipsca.com
- serial:00
-
- X509v3 Basic Constraints:
- CA:TRUE
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Extended Key Usage:
- TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping, Microsoft Encrypted File System
- X509v3 Subject Alternative Name:
- email:global01@ipsca.com
- X509v3 Issuer Alternative Name:
- email:global01@ipsca.com
- X509v3 CRL Distribution Points:
-
- Full Name:
- URI:http://crlglobal01.ipsca.com/crl/crlglobal01.crl
-
- Authority Information Access:
- OCSP - URI:http://crlglobal01.ipsca.com
-
- Signature Algorithm: sha1WithRSAEncryption
- 18:f4:ae:fe:80:0f:8e:c1:77:6f:a2:5a:47:48:9f:23:55:a1:
- 53:6b:f9:5d:a7:30:a5:24:be:43:2f:f8:c1:d1:57:f9:3e:2c:
- 80:25:cc:46:a9:36:f3:49:5b:1d:f6:7c:d7:63:b3:4d:3e:78:
- f6:a7:b4:02:77:f8:79:0d:3e:6a:cb:18:60:b8:fd:00:af:0c:
- dd:54:e3:54:8f:22:3d:f3:10:6f:11:0d:b5:1e:7a:8d:27:cc:
- 08:b8:5b:c3:b8:1a:5f:2b:a7:60:3f:00:1c:f7:0f:5c:42:66:
- 64:9e:87:12:80:70:89:e0:fa:57:28:0e:4e:1f:10:2f:d9:05:
- 80:b6:80:2f:1c:69:f0:f6:b6:65:34:05:6f:ca:d9:3e:f8:d4:
- 5d:37:32:c7:b8:2b:cc:ff:73:93:00:71:e0:01:c8:aa:43:bd:
- a9:f1:ce:fa:80:f9:f1:43:12:91:a6:65:e5:60:07:4d:47:ba:
- 2b:2f:04:f6:4a:85:29:88:65:10:c9:b2:53:62:9c:6c:9b:60:
- 5c:1a:1b:d3:ae:c5:1d:72:99:06:ff:05:cc:86:26:73:b4:d4:
- 54:05:dd:1e:6b:00:3b:b7:89:e8:e3:91:02:20:12:eb:ef:e9:
- fe:0a:29:23:81:23:a3:00:da:70:cc:92:5f:37:23:d0:1c:7b:
- 35:5c:03:7a
-SHA1 Fingerprint=3C:71:D7:0E:35:A5:DA:A8:B2:E3:81:2D:C3:67:74:17:F5:99:0D:F3
diff --git a/luni/src/main/files/cacerts/1df5ec47.0 b/luni/src/main/files/cacerts/1df5ec47.0
deleted file mode 100644
index 72ac6b8..0000000
--- a/luni/src/main/files/cacerts/1df5ec47.0
+++ /dev/null
@@ -1,84 +0,0 @@
------BEGIN CERTIFICATE-----
-MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
-BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1
-c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy
-MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl
-ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm
-BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF
-5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv
-DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v
-zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT
-yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj
-dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh
-MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB
-Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI
-4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz
-dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY
-aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G
-DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV
-CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH
-LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number:
- 63:25:00:01:00:02:14:8d:33:15:02:e4:6c:f4
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Universal CA, CN=TC TrustCenter Universal CA III
- Validity
- Not Before: Sep 9 08:15:27 2009 GMT
- Not After : Dec 31 23:59:59 2029 GMT
- Subject: C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Universal CA, CN=TC TrustCenter Universal CA III
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:c2:da:9c:62:b0:b9:71:12:b0:0b:c8:1a:57:b2:
- ae:83:14:99:b3:34:4b:9b:90:a2:c5:e7:e7:2f:02:
- a0:4d:2d:a4:fa:85:da:9b:25:85:2d:40:28:20:6d:
- ea:e0:bd:b1:48:83:22:29:44:9f:4e:83:ee:35:51:
- 13:73:74:d5:bc:f2:30:66:94:53:c0:40:36:2f:0c:
- 84:65:ce:0f:6e:c2:58:93:e8:2c:0b:3a:e9:c1:8e:
- fb:f2:6b:ca:3c:e2:9c:4e:8e:e4:f9:7d:d3:27:9f:
- 1b:d5:67:78:87:2d:7f:0b:47:b3:c7:e8:c9:48:7c:
- af:2f:cc:0a:d9:41:ef:9f:fe:9a:e1:b2:ae:f9:53:
- b5:e5:e9:46:9f:60:e3:df:8d:d3:7f:fb:96:7e:b3:
- b5:72:f8:4b:ad:08:79:cd:69:89:40:27:f5:2a:c1:
- ad:43:ec:a4:53:c8:61:b6:f7:d2:79:2a:67:18:76:
- 48:6d:5b:25:01:d1:26:c5:b7:57:69:23:15:5b:61:
- 8a:ad:f0:1b:2d:d9:af:5c:f1:26:90:69:a9:d5:0c:
- 40:f5:33:80:43:8f:9c:a3:76:2a:45:b4:af:bf:7f:
- 3e:87:3f:76:c5:cd:2a:de:20:c5:16:58:cb:f9:1b:
- f5:0f:cb:0d:11:52:64:b8:d2:76:62:77:83:f1:58:
- 9f:ff
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Authority Key Identifier:
- keyid:56:E7:E1:5B:25:43:80:E0:F6:8C:E1:71:BC:8E:E5:80:2F:C4:48:E2
-
- X509v3 Basic Constraints: critical
- CA:TRUE
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- 56:E7:E1:5B:25:43:80:E0:F6:8C:E1:71:BC:8E:E5:80:2F:C4:48:E2
- Signature Algorithm: sha1WithRSAEncryption
- 83:c7:af:ea:7f:4d:0a:3c:39:b1:68:be:7b:6d:89:2e:e9:b3:
- 09:e7:18:57:8d:85:9a:17:f3:76:42:50:13:0f:c7:90:6f:33:
- ad:c5:49:60:2b:6c:49:58:19:d4:e2:be:b7:bf:ab:49:bc:94:
- c8:ab:be:28:6c:16:68:e0:c8:97:46:20:a0:68:67:60:88:39:
- 20:51:d8:68:01:11:ce:a7:f6:11:07:f6:ec:ec:ac:1a:1f:b2:
- 66:6e:56:67:60:7a:74:5e:c0:6d:97:36:ae:b5:0d:5d:66:73:
- c0:25:32:45:d8:4a:06:07:8f:c4:b7:07:b1:4d:06:0d:e1:a5:
- eb:f4:75:ca:ba:9c:d0:bd:b3:d3:32:24:4c:ee:7e:e2:76:04:
- 4b:49:53:d8:f2:e9:54:33:fc:e5:71:1f:3d:14:5c:96:4b:f1:
- 3a:f2:00:bb:6c:b4:fa:96:55:08:88:09:c1:cc:91:19:29:b0:
- 20:2d:ff:cb:38:a4:40:e1:17:be:79:61:80:ff:07:03:86:4c:
- 4e:7b:06:9f:11:86:8d:89:ee:27:c4:db:e2:bc:19:8e:0b:c3:
- c3:13:c7:2d:03:63:3b:d3:e8:e4:a2:2a:c2:82:08:94:16:54:
- f0:ef:1f:27:90:25:b8:0d:0e:28:1b:47:77:47:bd:1c:a8:25:
- f1:94:b4:66
-SHA1 Fingerprint=96:56:CD:7B:57:96:98:95:D0:E1:41:46:68:06:FB:B8:C6:11:06:87
diff --git a/luni/src/main/files/cacerts/21855f49.0 b/luni/src/main/files/cacerts/21855f49.0
new file mode 100644
index 0000000..afaaf34
--- /dev/null
+++ b/luni/src/main/files/cacerts/21855f49.0
@@ -0,0 +1,119 @@
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy
+MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk
+D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o
+OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A
+fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe
+IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n
+oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK
+/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj
+rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD
+3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE
+7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC
+yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd
+qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI
+hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
+xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA
+SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo
+HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB
+emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC
+AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb
+7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x
+DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk
+F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF
+a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT
+Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 14052245610670616104 (0xc3039aee50906e28)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R1
+ Validity
+ Not Before: Jul 19 09:06:56 2012 GMT
+ Not After : Jul 19 09:06:56 2042 GMT
+ Subject: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:aa:c3:78:f7:dc:98:a3:a7:5a:5e:77:18:b2:dd:
+ 04:64:0f:63:fd:9b:96:09:80:d5:e8:aa:a5:e2:9c:
+ 26:94:3a:e8:99:73:8c:9d:df:d7:df:83:f3:78:4f:
+ 40:e1:7f:d2:a7:d2:e5:ca:13:93:e7:ed:c6:77:5f:
+ 36:b5:94:af:e8:38:8e:db:9b:e5:7c:bb:cc:8d:eb:
+ 75:73:e1:24:cd:e6:a7:2d:19:2e:d8:d6:8a:6b:14:
+ eb:08:62:0a:d8:dc:b3:00:4d:c3:23:7c:5f:43:08:
+ 23:32:12:dc:ed:0c:ad:c0:7d:0f:a5:7a:42:d9:5a:
+ 70:d9:bf:a7:d7:01:1c:f6:9b:ab:8e:b7:4a:86:78:
+ a0:1e:56:31:ae:ef:82:0a:80:41:f7:1b:c9:ae:ab:
+ 32:26:d4:2c:6b:ed:7d:6b:e4:e2:5e:22:0a:45:cb:
+ 84:31:4d:ac:fe:db:d1:47:ba:f9:60:97:39:b1:65:
+ c7:de:fb:99:e4:0a:22:b1:2d:4d:e5:48:26:69:ab:
+ e2:aa:f3:fb:fc:92:29:32:e9:b3:3e:4d:1f:27:a1:
+ cd:8e:b9:17:fb:25:3e:c9:6e:f3:77:da:0d:12:f6:
+ 5d:c7:bb:36:10:d5:54:d6:f3:e0:e2:47:48:e6:de:
+ 14:da:61:52:af:26:b4:f5:71:4f:c9:d7:d2:06:df:
+ 63:ca:ff:21:e8:59:06:e0:08:d5:84:15:53:f7:43:
+ e5:7c:c5:a0:89:98:6b:73:c6:68:ce:65:de:bd:7f:
+ 05:f7:b1:ee:f6:57:a1:60:95:c5:cc:ea:93:3a:be:
+ 99:ae:9b:02:a3:ad:c9:16:b5:ce:dd:5e:99:78:7e:
+ 1a:39:7e:b2:c0:05:a4:c0:82:a5:a3:47:9e:8c:ea:
+ 5c:b6:bc:67:db:e6:2a:4d:d2:04:dc:a3:ae:45:f7:
+ bc:8b:9c:1c:a7:d6:d5:03:dc:08:cb:2e:16:ca:5c:
+ 40:33:e8:67:c3:2e:e7:a6:44:ea:11:45:1c:35:65:
+ 2d:1e:45:61:24:1b:82:2e:a5:9d:33:5d:65:f8:41:
+ f9:2e:cb:94:3f:1f:a3:0c:31:24:44:ed:c7:5e:ad:
+ 50:ba:c6:41:9b:ac:f0:17:65:c0:f8:5d:6f:5b:a0:
+ 0a:34:3c:ee:d7:ea:88:9f:98:f9:af:4e:24:fa:97:
+ b2:64:76:da:ab:f4:ed:e3:c3:60:ef:d5:f9:02:c8:
+ 2d:9f:83:af:67:69:06:a7:31:55:d5:cf:4b:6f:ff:
+ 04:05:c7:58:ac:5f:16:1b:e5:d2:a3:eb:31:db:1f:
+ 33:15:4d:d0:f2:a5:53:f5:cb:e1:3d:4e:68:2d:d8:
+ 12:dd:aa:f2:e6:4d:9b:49:e5:c5:28:a1:ba:b0:5a:
+ c6:a0:b5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 89:0A:B4:38:93:1A:E6:AB:EE:9B:91:18:F9:F5:3C:3E:35:D0:D3:82
+ Signature Algorithm: sha1WithRSAEncryption
+ 32:8b:f6:9d:4a:c9:be:14:e5:8c:ac:38:ca:3a:09:d4:1b:ce:
+ 86:b3:dd:eb:d4:ba:28:be:12:ae:45:2c:04:74:ac:13:51:c5:
+ 58:18:66:4d:82:da:d5:dc:93:c0:27:e1:be:7c:9f:52:9e:12:
+ 56:f6:d5:9c:a9:f4:75:9c:fa:37:12:8f:1c:93:ec:57:fe:07:
+ 0f:ab:d5:12:f7:0f:ae:61:5e:56:80:49:f5:fc:30:f5:9b:4f:
+ 1f:41:2f:1c:84:d3:89:c7:e2:da:02:76:ed:09:cf:6c:c1:b8:
+ 1c:83:1c:16:fa:94:cd:7d:a0:c8:18:d2:c8:9d:6e:f5:bd:69:
+ d4:6d:3d:35:e8:1e:a2:4f:60:d7:07:29:fc:b2:a3:a4:9d:6e:
+ 15:92:56:19:4c:0a:b0:e9:7c:d2:19:4d:42:46:ec:bd:fd:f6:
+ 57:5b:dd:98:7e:a4:4d:cc:72:03:83:58:5d:ef:93:3a:41:7a:
+ 63:aa:7c:3a:a8:f5:ac:a4:d1:dd:a2:2d:b6:2a:fc:9f:01:8e:
+ e2:10:b1:c4:ca:e4:67:db:55:25:19:3f:fd:e8:36:7e:b3:e1:
+ e1:81:af:11:16:8b:50:97:60:19:82:00:c0:6b:4d:73:b8:d1:
+ 13:07:3e:ea:b6:31:4f:f0:42:9a:6d:e2:11:74:e5:94:ac:8d:
+ 84:95:3c:21:af:c5:da:47:c8:df:39:62:62:cb:5b:50:0b:d7:
+ 81:40:05:9c:9b:ed:ba:b6:8b:1e:04:6f:96:20:39:ed:a4:7d:
+ 29:db:48:ce:82:dc:d4:02:8d:1d:04:31:5a:c7:4b:f0:6c:61:
+ 52:d7:b4:51:c2:81:6c:cd:e1:fb:a7:a1:d2:92:76:cf:b1:0f:
+ 37:58:a4:f2:52:71:67:3f:0c:88:78:80:89:c1:c8:b5:1f:92:
+ 63:be:a7:7a:8a:56:2c:1a:a8:a6:9c:b5:5d:b3:63:d0:13:20:
+ a1:eb:91:6c:d0:8d:7d:af:df:0b:e4:17:b9:86:9e:38:b1:94:
+ 0c:58:8c:e0:55:aa:3b:63:6d:9a:89:60:b8:64:2a:92:c6:37:
+ f4:7e:43:43:b7:73:e8:01:e7:7f:97:0f:d7:f2:7b:19:fd:1a:
+ d7:8f:c9:fa:85:6b:7a:9d:9e:89:b6:a6:28:99:93:88:40:f7:
+ 3e:cd:51:a3:ca:ea:ef:79:47:21:b5:fe:32:e2:c7:c3:51:6f:
+ be:80:74:f0:a4:c3:3a:f2:4f:e9:5f:df:19:0a:f2:3b:13:43:
+ ac:31:a4:b3:e7:eb:fc:18:d6:01:a9:f3:2a:8f:36:0e:eb:b4:
+ b1:bc:b7:4c:c9:6b:bf:a1:f3:d9:f4:ed:e2:f0:e3:ed:64:9e:
+ 3d:2f:96:52:4f:80:53:8b
+SHA1 Fingerprint=8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6
diff --git a/luni/src/main/files/cacerts/33815e15.1 b/luni/src/main/files/cacerts/33815e15.1
new file mode 100644
index 0000000..8f3271c
--- /dev/null
+++ b/luni/src/main/files/cacerts/33815e15.1
@@ -0,0 +1,147 @@
+-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC
+ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w
+ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk
+aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0
+YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg
+c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93
+d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG
+CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF
+wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS
+Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst
+0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc
+pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl
+CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF
+P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK
+1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm
+KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ
+8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm
+fyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 45 (0x2d)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority
+ Validity
+ Not Before: Sep 17 19:46:37 2006 GMT
+ Not After : Sep 17 19:46:36 2036 GMT
+ Subject: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:c1:88:db:09:bc:6c:46:7c:78:9f:95:7b:b5:33:
+ 90:f2:72:62:d6:c1:36:20:22:24:5e:ce:e9:77:f2:
+ 43:0a:a2:06:64:a4:cc:8e:36:f8:38:e6:23:f0:6e:
+ 6d:b1:3c:dd:72:a3:85:1c:a1:d3:3d:b4:33:2b:d3:
+ 2f:af:fe:ea:b0:41:59:67:b6:c4:06:7d:0a:9e:74:
+ 85:d6:79:4c:80:37:7a:df:39:05:52:59:f7:f4:1b:
+ 46:43:a4:d2:85:85:d2:c3:71:f3:75:62:34:ba:2c:
+ 8a:7f:1e:8f:ee:ed:34:d0:11:c7:96:cd:52:3d:ba:
+ 33:d6:dd:4d:de:0b:3b:4a:4b:9f:c2:26:2f:fa:b5:
+ 16:1c:72:35:77:ca:3c:5d:e6:ca:e1:26:8b:1a:36:
+ 76:5c:01:db:74:14:25:fe:ed:b5:a0:88:0f:dd:78:
+ ca:2d:1f:07:97:30:01:2d:72:79:fa:46:d6:13:2a:
+ a8:b9:a6:ab:83:49:1d:e5:f2:ef:dd:e4:01:8e:18:
+ 0a:8f:63:53:16:85:62:a9:0e:19:3a:cc:b5:66:a6:
+ c2:6b:74:07:e4:2b:e1:76:3e:b4:6d:d8:f6:44:e1:
+ 73:62:1f:3b:c4:be:a0:53:56:25:6c:51:09:f7:aa:
+ ab:ca:bf:76:fd:6d:9b:f3:9d:db:bf:3d:66:bc:0c:
+ 56:aa:af:98:48:95:3a:4b:df:a7:58:50:d9:38:75:
+ a9:5b:ea:43:0c:02:ff:99:eb:e8:6c:4d:70:5b:29:
+ 65:9c:dd:aa:5d:cc:af:01:31:ec:0c:eb:d2:8d:e8:
+ ea:9c:7b:e6:6e:f7:27:66:0c:1a:48:d7:6e:42:e3:
+ 3f:de:21:3e:7b:e1:0d:70:fb:63:aa:a8:6c:1a:54:
+ b4:5c:25:7a:c9:a2:c9:8b:16:a6:bb:2c:7e:17:5e:
+ 05:4d:58:6e:12:1d:01:ee:12:10:0d:c6:32:7f:18:
+ ff:fc:f4:fa:cd:6e:91:e8:36:49:be:1a:48:69:8b:
+ c2:96:4d:1a:12:b2:69:17:c1:0a:90:d6:fa:79:22:
+ 48:bf:ba:7b:69:f8:70:c7:fa:7a:37:d8:d8:0d:d2:
+ 76:4f:57:ff:90:b7:e3:91:d2:dd:ef:c2:60:b7:67:
+ 3a:dd:fe:aa:9c:f0:d4:8b:7f:72:22:ce:c6:9f:97:
+ b6:f8:af:8a:a0:10:a8:d9:fb:18:c6:b6:b5:5c:52:
+ 3c:89:b6:19:2a:73:01:0a:0f:03:b3:12:60:f2:7a:
+ 2f:81:db:a3:6e:ff:26:30:97:f5:8b:dd:89:57:b6:
+ ad:3d:b3:af:2b:c5:b7:76:02:f0:a5:d6:2b:9a:86:
+ 14:2a:72:f6:e3:33:8c:5d:09:4b:13:df:bb:8c:74:
+ 13:52:4b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 4E:0B:EF:1A:A4:40:5B:A5:17:69:87:30:CA:34:68:43:D0:41:AE:F2
+ X509v3 Authority Key Identifier:
+ keyid:4E:0B:EF:1A:A4:40:5B:A5:17:69:87:30:CA:34:68:43:D0:41:AE:F2
+
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.23223.1.1.1
+ CPS: http://www.startssl.com/policy.pdf
+ CPS: http://www.startssl.com/intermediate.pdf
+ User Notice:
+ Organization: Start Commercial (StartCom) Ltd.
+ Number: 1
+ Explicit Text: Limited Liability, read the section *Legal Limitations* of the StartCom Certification Authority Policy available at http://www.startssl.com/policy.pdf
+
+ Netscape Cert Type:
+ SSL CA, S/MIME CA, Object Signing CA
+ Netscape Comment:
+ StartCom Free SSL Certification Authority
+ Signature Algorithm: sha256WithRSAEncryption
+ 8e:8f:e7:dc:94:79:7c:f1:85:7f:9f:49:6f:6b:ca:5d:fb:8c:
+ fe:04:c5:c1:62:d1:7d:42:8a:bc:53:b7:94:03:66:30:3f:b1:
+ e7:0a:a7:50:20:55:25:7f:76:7a:14:0d:eb:04:0e:40:e6:3e:
+ d8:88:ab:07:27:83:a9:75:a6:37:73:c7:fd:4b:d2:4d:ad:17:
+ 40:c8:46:be:3b:7f:51:fc:c3:b6:05:31:dc:cd:85:22:4e:71:
+ b7:f2:71:5e:b0:1a:c6:ba:93:8b:78:92:4a:85:f8:78:0f:83:
+ fe:2f:ad:2c:f7:e4:a4:bb:2d:d0:e7:0d:3a:b8:3e:ce:f6:78:
+ f6:ae:47:24:ca:a3:35:36:ce:c7:c6:87:98:da:ec:fb:e9:b2:
+ ce:27:9b:88:c3:04:a1:f6:0b:59:68:af:c9:db:10:0f:4d:f6:
+ 64:63:5c:a5:12:6f:92:b2:93:94:c7:88:17:0e:93:b6:7e:62:
+ 8b:90:7f:ab:4e:9f:fc:e3:75:14:4f:2a:32:df:5b:0d:e0:f5:
+ 7b:93:0d:ab:a1:cf:87:e1:a5:04:45:e8:3c:12:a5:09:c5:b0:
+ d1:b7:53:f3:60:14:ba:85:69:6a:21:7c:1f:75:61:17:20:17:
+ 7b:6c:3b:41:29:5c:e1:ac:5a:d1:cd:8c:9b:eb:60:1d:19:ec:
+ f7:e5:b0:da:f9:79:18:a5:45:3f:49:43:57:d2:dd:24:d5:2c:
+ a3:fd:91:8d:27:b5:e5:eb:14:06:9a:4c:7b:21:bb:3a:ad:30:
+ 06:18:c0:d8:c1:6b:2c:7f:59:5c:5d:91:b1:70:22:57:eb:8a:
+ 6b:48:4a:d5:0f:29:ec:c6:40:c0:2f:88:4c:68:01:17:77:f4:
+ 24:19:4f:bd:fa:e1:b2:20:21:4b:dd:1a:d8:29:7d:aa:b8:de:
+ 54:ec:21:55:80:6c:1e:f5:30:c8:a3:10:e5:b2:e6:2a:14:31:
+ c3:85:2d:8c:98:b1:86:5a:4f:89:59:2d:b9:c7:f7:1c:c8:8a:
+ 7f:c0:9d:05:4a:e6:42:4f:62:a3:6d:29:a4:1f:85:ab:db:e5:
+ 81:c8:ad:2a:3d:4c:5d:5b:84:26:71:c4:85:5e:71:24:ca:a5:
+ 1b:6c:d8:61:d3:1a:e0:54:db:ce:ba:a9:32:b5:22:f6:73:41:
+ 09:5d:b8:17:5d:0e:0f:99:90:d6:47:da:6f:0a:3a:62:28:14:
+ 67:82:d9:f1:d0:80:59:9b:cb:31:d8:9b:0f:8c:77:4e:b5:68:
+ 8a:f2:6c:f6:24:0e:2d:6c:70:c5:73:d1:de:14:d0:71:8f:b6:
+ d3:7b:02:f6:e3:b8:d4:09:6e:6b:9e:75:84:39:e6:7f:25:a5:
+ f2:48:00:c0:a4:01:da:3f
+SHA1 Fingerprint=A3:F1:33:3F:E2:42:BF:CF:C5:D1:4E:8F:39:42:98:40:68:10:D1:A0
diff --git a/luni/src/main/files/cacerts/3c9a4d3b.0 b/luni/src/main/files/cacerts/3c9a4d3b.0
new file mode 100644
index 0000000..c6e312c
--- /dev/null
+++ b/luni/src/main/files/cacerts/3c9a4d3b.0
@@ -0,0 +1,152 @@
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE
+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw
+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ
+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND
+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb
+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY
+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo
+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA
+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr
+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/
+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH
+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47
+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO
+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa
+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl
+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI
+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls
+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG
+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT
+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG
+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA
+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA
+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA
+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA
+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA
+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA
+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu
+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt
+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF
+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp
+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU
+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m
+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD
+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms
+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH
+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA
+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF
+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H
+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6828503384748696800 (0x5ec3b7a6437fa4e0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=ACCVRAIZ1, OU=PKIACCV, O=ACCV, C=ES
+ Validity
+ Not Before: May 5 09:37:37 2011 GMT
+ Not After : Dec 31 09:37:37 2030 GMT
+ Subject: CN=ACCVRAIZ1, OU=PKIACCV, O=ACCV, C=ES
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:9b:a9:ab:bf:61:4a:97:af:2f:97:66:9a:74:5f:
+ d0:d9:96:fd:cf:e2:e4:66:ef:1f:1f:47:33:c2:44:
+ a3:df:9a:de:1f:b5:54:dd:15:7c:69:35:11:6f:bb:
+ c8:0c:8e:6a:18:1e:d8:8f:d9:16:bc:10:48:36:5c:
+ f0:63:b3:90:5a:5c:24:37:d7:a3:d6:cb:09:71:b9:
+ f1:01:72:84:b0:7d:db:4d:80:cd:fc:d3:6f:c9:f8:
+ da:b6:0e:82:d2:45:85:a8:1b:68:a8:3d:e8:f4:44:
+ 6c:bd:a1:c2:cb:03:be:8c:3e:13:00:84:df:4a:48:
+ c0:e3:22:0a:e8:e9:37:a7:18:4c:b1:09:0d:23:56:
+ 7f:04:4d:d9:17:84:18:a5:c8:da:40:94:73:eb:ce:
+ 0e:57:3c:03:81:3a:9d:0a:a1:57:43:69:ac:57:6d:
+ 79:90:78:e5:b5:b4:3b:d8:bc:4c:8d:28:a1:a7:a3:
+ a7:ba:02:4e:25:d1:2a:ae:ed:ae:03:22:b8:6b:20:
+ 0f:30:28:54:95:7f:e0:ee:ce:0a:66:9d:d1:40:2d:
+ 6e:22:af:9d:1a:c1:05:19:d2:6f:c0:f2:9f:f8:7b:
+ b3:02:42:fb:50:a9:1d:2d:93:0f:23:ab:c6:c1:0f:
+ 92:ff:d0:a2:15:f5:53:09:71:1c:ff:45:13:84:e6:
+ 26:5e:f8:e0:88:1c:0a:fc:16:b6:a8:73:06:b8:f0:
+ 63:84:02:a0:c6:5a:ec:e7:74:df:70:ae:a3:83:25:
+ ea:d6:c7:97:87:93:a7:c6:8a:8a:33:97:60:37:10:
+ 3e:97:3e:6e:29:15:d6:a1:0f:d1:88:2c:12:9f:6f:
+ aa:a4:c6:42:eb:41:a2:e3:95:43:d3:01:85:6d:8e:
+ bb:3b:f3:23:36:c7:fe:3b:e0:a1:25:07:48:ab:c9:
+ 89:74:ff:08:8f:80:bf:c0:96:65:f3:ee:ec:4b:68:
+ bd:9d:88:c3:31:b3:40:f1:e8:cf:f6:38:bb:9c:e4:
+ d1:7f:d4:e5:58:9b:7c:fa:d4:f3:0e:9b:75:91:e4:
+ ba:52:2e:19:7e:d1:f5:cd:5a:19:fc:ba:06:f6:fb:
+ 52:a8:4b:99:04:dd:f8:f9:b4:8b:50:a3:4e:62:89:
+ f0:87:24:fa:83:42:c1:87:fa:d5:2d:29:2a:5a:71:
+ 7a:64:6a:d7:27:60:63:0d:db:ce:49:f5:8d:1f:90:
+ 89:32:17:f8:73:43:b8:d2:5a:93:86:61:d6:e1:75:
+ 0a:ea:79:66:76:88:4f:71:eb:04:25:d6:0a:5a:7a:
+ 93:e5:b9:4b:17:40:0f:b1:b6:b9:f5:de:4f:dc:e0:
+ b3:ac:3b:11:70:60:84:4a:43:6e:99:20:c0:29:71:
+ 0a:c0:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ CA Issuers - URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1.crt
+ OCSP - URI:http://ocsp.accv.es
+
+ X509v3 Subject Key Identifier:
+ D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD
+
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ User Notice:
+ Explicit Text:
+ CPS: http://www.accv.es/legislacion_c.htm
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1_der.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Alternative Name:
+ email:accv@accv.es
+ Signature Algorithm: sha1WithRSAEncryption
+ 97:31:02:9f:e7:fd:43:67:48:44:14:e4:29:87:ed:4c:28:66:
+ d0:8f:35:da:4d:61:b7:4a:97:4d:b5:db:90:e0:05:2e:0e:c6:
+ 79:d0:f2:97:69:0f:bd:04:47:d9:be:db:b5:29:da:9b:d9:ae:
+ a9:99:d5:d3:3c:30:93:f5:8d:a1:a8:fc:06:8d:44:f4:ca:16:
+ 95:7c:33:dc:62:8b:a8:37:f8:27:d8:09:2d:1b:ef:c8:14:27:
+ 20:a9:64:44:ff:2e:d6:75:aa:6c:4d:60:40:19:49:43:54:63:
+ da:e2:cc:ba:66:e5:4f:44:7a:5b:d9:6a:81:2b:40:d5:7f:f9:
+ 01:27:58:2c:c8:ed:48:91:7c:3f:a6:00:cf:c4:29:73:11:36:
+ de:86:19:3e:9d:ee:19:8a:1b:d5:b0:ed:8e:3d:9c:2a:c0:0d:
+ d8:3d:66:e3:3c:0d:bd:d5:94:5c:e2:e2:a7:35:1b:04:00:f6:
+ 3f:5a:8d:ea:43:bd:5f:89:1d:a9:c1:b0:cc:99:e2:4d:00:0a:
+ da:c9:27:5b:e7:13:90:5c:e4:f5:33:a2:55:6d:dc:e0:09:4d:
+ 2f:b1:26:5b:27:75:00:09:c4:62:77:29:08:5f:9e:59:ac:b6:
+ 7e:ad:9f:54:30:22:03:c1:1e:71:64:fe:f9:38:0a:96:18:dd:
+ 02:14:ac:23:cb:06:1c:1e:a4:7d:8d:0d:de:27:41:e8:ad:da:
+ 15:b7:b0:23:dd:2b:a8:d3:da:25:87:ed:e8:55:44:4d:88:f4:
+ 36:7e:84:9a:78:ac:f7:0e:56:49:0e:d6:33:25:d6:84:50:42:
+ 6c:20:12:1d:2a:d5:be:bc:f2:70:81:a4:70:60:be:05:b5:9b:
+ 9e:04:44:be:61:23:ac:e9:a5:24:8c:11:80:94:5a:a2:a2:b9:
+ 49:d2:c1:dc:d1:a7:ed:31:11:2c:9e:19:a6:ee:e1:55:e1:c0:
+ ea:cf:0d:84:e4:17:b7:a2:7c:a5:de:55:25:06:ee:cc:c0:87:
+ 5c:40:da:cc:95:3f:55:e0:35:c7:b8:84:be:b4:5d:cd:7a:83:
+ 01:72:ee:87:e6:5f:1d:ae:b5:85:c6:26:df:e6:c1:9a:e9:1e:
+ 02:47:9f:2a:a8:6d:a9:5b:cf:ec:45:77:7f:98:27:9a:32:5d:
+ 2a:e3:84:ee:c5:98:66:2f:96:20:1d:dd:d8:c3:27:d7:b0:f9:
+ fe:d9:7d:cd:d0:9f:8f:0b:14:58:51:9f:2f:8b:c3:38:2d:de:
+ e8:8f:d6:8d:87:a4:f5:56:43:16:99:2c:f4:a4:56:b4:34:b8:
+ 61:37:c9:c2:58:80:1b:a0:97:a1:fc:59:8d:e9:11:f6:d1:0f:
+ 4b:55:34:46:2a:8b:86:3b
+SHA1 Fingerprint=93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17
diff --git a/luni/src/main/files/cacerts/40dc992e.0 b/luni/src/main/files/cacerts/40dc992e.0
new file mode 100644
index 0000000..847cec6
--- /dev/null
+++ b/luni/src/main/files/cacerts/40dc992e.0
@@ -0,0 +1,93 @@
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix
+RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p
+YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw
+NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK
+EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl
+cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz
+dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ
+fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns
+bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD
+75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP
+FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV
+HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp
+5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu
+b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA
+A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p
+6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7
+dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys
+Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI
+l7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GR, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions RootCA 2011
+ Validity
+ Not Before: Dec 6 13:49:52 2011 GMT
+ Not After : Dec 1 13:49:52 2031 GMT
+ Subject: C=GR, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions RootCA 2011
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a9:53:00:e3:2e:a6:f6:8e:fa:60:d8:2d:95:3e:
+ f8:2c:2a:54:4e:cd:b9:84:61:94:58:4f:8f:3d:8b:
+ e4:43:f3:75:89:8d:51:e4:c3:37:d2:8a:88:4d:79:
+ 1e:b7:12:dd:43:78:4a:8a:92:e6:d7:48:d5:0f:a4:
+ 3a:29:44:35:b8:07:f6:68:1d:55:cd:38:51:f0:8c:
+ 24:31:85:af:83:c9:7d:e9:77:af:ed:1a:7b:9d:17:
+ f9:b3:9d:38:50:0f:a6:5a:79:91:80:af:37:ae:a6:
+ d3:31:fb:b5:26:09:9d:3c:5a:ef:51:c5:2b:df:96:
+ 5d:eb:32:1e:02:da:70:49:ec:6e:0c:c8:9a:37:8d:
+ f7:f1:36:60:4b:26:2c:82:9e:d0:78:f3:0d:0f:63:
+ a4:51:30:e1:f9:2b:27:12:07:d8:ea:bd:18:62:98:
+ b0:59:37:7d:be:ee:f3:20:51:42:5a:83:ef:93:ba:
+ 69:15:f1:62:9d:9f:99:39:82:a1:b7:74:2e:8b:d4:
+ c5:0b:7b:2f:f0:c8:0a:da:3d:79:0a:9a:93:1c:a5:
+ 28:72:73:91:43:9a:a7:d1:4d:85:84:b9:a9:74:8f:
+ 14:40:c7:dc:de:ac:41:64:6c:b4:19:9b:02:63:6d:
+ 24:64:8f:44:b2:25:ea:ce:5d:74:0c:63:32:5c:8d:
+ 87:e5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ A6:91:42:FD:13:61:4A:23:9E:08:A4:29:E5:D8:13:04:23:EE:41:25
+ X509v3 Name Constraints:
+ Permitted:
+ DNS:.gr
+ DNS:.eu
+ DNS:.edu
+ DNS:.org
+ email:.gr
+ email:.eu
+ email:.edu
+ email:.org
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 1f:ef:79:41:e1:7b:6e:3f:b2:8c:86:37:42:4a:4e:1c:37:1e:
+ 8d:66:ba:24:81:c9:4f:12:0f:21:c0:03:97:86:25:6d:5d:d3:
+ 22:29:a8:6c:a2:0d:a9:eb:3d:06:5b:99:3a:c7:cc:c3:9a:34:
+ 7f:ab:0e:c8:4e:1c:e1:fa:e4:dc:cd:0d:be:bf:24:fe:6c:e7:
+ 6b:c2:0d:c8:06:9e:4e:8d:61:28:a6:6a:fd:e5:f6:62:ea:18:
+ 3c:4e:a0:53:9d:b2:3a:9c:eb:a5:9c:91:16:b6:4d:82:e0:0c:
+ 05:48:a9:6c:f5:cc:f8:cb:9d:49:b4:f0:02:a5:fd:70:03:ed:
+ 8a:21:a5:ae:13:86:49:c3:33:73:be:87:3b:74:8b:17:45:26:
+ 4c:16:91:83:fe:67:7d:cd:4d:63:67:fa:f3:03:12:96:78:06:
+ 8d:b1:67:ed:8e:3f:be:9f:4f:02:f5:b3:09:2f:f3:4c:87:df:
+ 2a:cb:95:7c:01:cc:ac:36:7a:bf:a2:73:7a:f7:8f:c1:b5:9a:
+ a1:14:b2:8f:33:9f:0d:ef:22:dc:66:7b:84:bd:45:17:06:3d:
+ 3c:ca:b9:77:34:8f:ca:ea:cf:3f:31:3e:e3:88:e3:80:49:25:
+ c8:97:b5:9d:9a:99:4d:b0:3c:f8:4a:00:9b:64:dd:9f:39:4b:
+ d1:27:d7:b8
+SHA1 Fingerprint=FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D
diff --git a/luni/src/main/files/cacerts/46b2fd3b.0 b/luni/src/main/files/cacerts/46b2fd3b.0
deleted file mode 100644
index ea3d6ba..0000000
--- a/luni/src/main/files/cacerts/46b2fd3b.0
+++ /dev/null
@@ -1,128 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
-BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu
-IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw
-WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD
-ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD
-ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y
-IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn
-IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+
-6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob
-jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw
-izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl
-+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY
-zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP
-pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF
-KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW
-ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB
-AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
-BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0
-ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW
-IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA
-A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0
-uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+
-FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7
-jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/
-u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D
-YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1
-puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa
-icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG
-DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x
-kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z
-Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g==
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 5670595323396054351 (0x4eb200670c035d4f)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=CH, O=SwissSign AG, CN=SwissSign Platinum CA - G2
- Validity
- Not Before: Oct 25 08:36:00 2006 GMT
- Not After : Oct 25 08:36:00 2036 GMT
- Subject: C=CH, O=SwissSign AG, CN=SwissSign Platinum CA - G2
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (4096 bit)
- Modulus:
- 00:ca:df:a2:02:e2:da:f8:fc:07:16:b1:de:60:aa:
- de:96:5c:64:1f:c7:2f:7e:cf:67:fa:44:42:d6:76:
- 63:95:ae:eb:af:72:20:8a:45:47:86:62:78:86:d6:
- 20:39:26:f4:ae:a3:fd:23:e7:a5:9c:b5:22:21:19:
- b7:37:93:22:c0:50:9c:82:7b:d4:d5:04:44:5c:cb:
- b4:c2:9f:92:be:24:d8:7b:67:22:e2:69:5f:e5:05:
- 78:d4:87:d9:71:70:33:25:53:b4:87:3b:29:90:28:
- 36:9a:55:44:30:68:a4:83:97:7f:0d:1e:9c:76:ff:
- 15:9d:60:97:00:8d:8a:85:03:ec:80:be:ea:2c:6e:
- 10:51:92:cc:7e:d5:a3:33:d8:d6:49:de:58:2a:af:
- f6:16:eb:4b:7b:90:32:97:b9:ba:9d:58:f1:f8:57:
- 49:04:1e:a2:5d:06:70:dd:71:db:f9:dd:8b:9a:1b:
- 8c:cf:3d:a3:4d:ce:cb:7c:f6:bb:9c:a0:fa:09:ce:
- 23:62:b2:e9:0d:1f:e2:72:28:8f:9f:ac:68:20:7d:
- 6f:3b:a8:85:31:09:7f:0b:c7:e8:65:e9:e3:78:0e:
- 09:67:30:8b:34:82:fb:5d:e0:cc:9d:81:6d:62:ee:
- 08:1e:04:2c:4e:9b:ec:fe:a9:4f:5f:fd:69:78:ef:
- 09:1f:a1:b4:bf:fa:f3:ef:90:1e:4c:05:8b:1e:ea:
- 7a:91:7a:c3:d7:e5:fb:30:bc:6c:1b:10:58:98:f7:
- 1a:5f:d0:29:32:03:13:46:4d:61:6a:85:4c:52:74:
- 2f:06:1f:7b:11:e2:84:97:c6:99:f3:6d:7f:d7:67:
- 83:7e:13:68:d8:71:28:5a:d8:ce:dd:e8:10:14:9a:
- fe:6d:23:87:6e:8e:5a:70:3c:d5:8d:09:00:a7:aa:
- bc:b0:31:37:6d:c8:84:14:1e:5b:bd:45:63:20:6b:
- 4b:74:8c:bd:db:3a:0e:c1:cf:5a:16:8f:a5:98:f2:
- 76:89:b2:13:12:3b:0b:77:77:ac:bb:e5:3c:29:4a:
- 92:72:ca:61:1a:2b:5e:4c:e2:83:74:77:fa:35:48:
- 7a:85:4d:8d:9a:53:c4:df:78:ca:97:91:48:2b:45:
- 2b:01:f7:1c:1a:a2:ed:18:ba:0a:bd:83:fa:6f:bc:
- 8d:57:93:3b:d4:d4:a6:ce:1e:f1:a0:b1:ce:ab:fd:
- 2b:28:9a:4f:1b:d7:c3:72:db:a4:c4:bf:5d:4c:f5:
- dd:7b:96:69:ee:68:80:e6:e7:98:ba:36:b7:fe:6e:
- ed:2b:bd:20:f8:65:19:da:55:09:7e:25:dc:fe:61:
- 62:72:f9:7e:18:02:ef:63:b4:d0:fb:af:e5:3b:63:
- 8c:67:8f
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Basic Constraints: critical
- CA:TRUE
- X509v3 Subject Key Identifier:
- 50:AF:CC:07:87:15:47:6F:38:C5:B4:65:D1:DE:95:AA:E9:DF:9C:CC
- X509v3 Authority Key Identifier:
- keyid:50:AF:CC:07:87:15:47:6F:38:C5:B4:65:D1:DE:95:AA:E9:DF:9C:CC
-
- X509v3 Certificate Policies:
- Policy: 2.16.756.1.89.1.1.1.1
- CPS: http://repository.swisssign.com/
-
- Signature Algorithm: sha1WithRSAEncryption
- 08:85:a6:f5:16:0c:fc:44:1a:c1:63:e0:f9:55:46:08:fc:70:
- 1c:42:28:96:8e:b7:c5:c1:41:75:4e:09:71:79:e5:6d:96:ca:
- 4b:a5:88:60:d0:30:74:b8:ca:08:dc:b4:30:9e:40:07:16:6b:
- 65:95:77:01:ae:a4:b7:35:0b:81:da:71:15:a9:74:17:38:7b:
- 58:ca:f9:2f:fb:c0:65:76:8d:5b:01:b9:7d:de:82:3d:64:b8:
- be:14:74:a3:0a:54:d3:2c:95:18:17:35:f5:51:6b:3f:8f:a2:
- 96:61:39:78:6b:4b:e5:a6:a0:f8:53:df:51:10:93:62:e7:80:
- 2f:e2:d1:e0:bc:8e:36:46:77:33:ec:b8:fb:8e:9a:2c:89:4d:
- 31:11:0f:26:9e:04:bb:b7:04:8d:0b:f2:b9:fc:5a:9d:3b:16:
- b7:2f:c8:98:ab:fe:8a:50:59:2e:a3:3b:fc:29:5d:8b:c1:4b:
- c9:e2:8a:13:1d:b1:bf:bb:42:1d:52:dd:4e:d8:14:5e:10:c6:
- 31:07:ef:71:27:f7:1b:39:09:dc:82:ea:8b:b3:95:86:5e:fd:
- f5:da:5d:31:a6:e0:31:b6:94:e6:44:49:74:c5:16:e5:f7:1f:
- 03:61:28:c5:c8:cb:12:a0:42:4b:f9:6b:88:08:8d:b4:32:18:
- f3:75:9f:c4:7f:00:4f:05:95:9c:a3:17:02:c3:b3:53:9b:aa:
- 20:39:29:2b:66:fa:9d:af:5e:b3:92:d2:b5:a6:e1:1a:f9:2d:
- 41:69:81:14:b4:b4:b5:ed:89:3d:ce:fb:a9:9d:35:42:44:b1:
- 1c:14:73:81:cf:2a:01:35:9a:31:d5:2d:8f:6d:84:df:80:4d:
- 57:e3:3f:c5:84:75:da:89:c6:30:bb:eb:8f:cb:22:08:a0:ae:
- aa:f1:03:6c:3a:4b:4d:09:a5:0e:72:c6:56:6b:21:42:4e:23:
- 25:14:68:ae:76:0a:7c:0c:07:70:64:f9:9a:2f:f6:05:39:26:
- c6:0c:8f:19:7f:43:5e:6e:f4:5b:15:2f:db:61:5d:e6:67:2f:
- 3f:08:94:f9:60:b4:98:31:da:74:f1:84:93:71:4d:5f:fb:60:
- 58:d1:fb:c4:c1:6d:89:a2:bb:20:1f:9d:71:91:cb:32:9b:13:
- 3d:3e:7d:92:52:35:ac:92:94:a2:d3:18:c2:7c:c7:ea:af:76:
- 05:16:dd:67:27:c2:7e:1c:07:22:21:f3:40:0a:1b:34:07:44:
- 13:c2:84:6a:8e:df:19:5a:bf:7f:eb:1d:e2:1a:38:d1:5c:af:
- 47:92:6b:80:b5:30:a5:c9:8d:d8:ab:31:81:1f:df:c2:66:37:
- d3:93:a9:85:86:79:65:d2
-SHA1 Fingerprint=56:E0:FA:C0:3B:8F:18:23:55:18:E5:D3:11:CA:E8:C2:43:31:AB:66
diff --git a/luni/src/main/files/cacerts/5f47b495.0 b/luni/src/main/files/cacerts/5f47b495.0
new file mode 100644
index 0000000..87cd715
--- /dev/null
+++ b/luni/src/main/files/cacerts/5f47b495.0
@@ -0,0 +1,124 @@
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6271844772424770508 (0x570a119742c4e3cc)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=IT, L=Milan, O=Actalis S.p.A./03358520967, CN=Actalis Authentication Root CA
+ Validity
+ Not Before: Sep 22 11:22:02 2011 GMT
+ Not After : Sep 22 11:22:02 2030 GMT
+ Subject: C=IT, L=Milan, O=Actalis S.p.A./03358520967, CN=Actalis Authentication Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:a7:c6:c4:a5:29:a4:2c:ef:e5:18:c5:b0:50:a3:
+ 6f:51:3b:9f:0a:5a:c9:c2:48:38:0a:c2:1c:a0:18:
+ 7f:91:b5:87:b9:40:3f:dd:1d:68:1f:08:83:d5:2d:
+ 1e:88:a0:f8:8f:56:8f:6d:99:02:92:90:16:d5:5f:
+ 08:6c:89:d7:e1:ac:bc:20:c2:b1:e0:83:51:8a:69:
+ 4d:00:96:5a:6f:2f:c0:44:7e:a3:0e:e4:91:cd:58:
+ ee:dc:fb:c7:1e:45:47:dd:27:b9:08:01:9f:a6:21:
+ 1d:f5:41:2d:2f:4c:fd:28:ad:e0:8a:ad:22:b4:56:
+ 65:8e:86:54:8f:93:43:29:de:39:46:78:a3:30:23:
+ ba:cd:f0:7d:13:57:c0:5d:d2:83:6b:48:4c:c4:ab:
+ 9f:80:5a:5b:3a:bd:c9:a7:22:3f:80:27:33:5b:0e:
+ b7:8a:0c:5d:07:37:08:cb:6c:d2:7a:47:22:44:35:
+ c5:cc:cc:2e:8e:dd:2a:ed:b7:7d:66:0d:5f:61:51:
+ 22:55:1b:e3:46:e3:e3:3d:d0:35:62:9a:db:af:14:
+ c8:5b:a1:cc:89:1b:e1:30:26:fc:a0:9b:1f:81:a7:
+ 47:1f:04:eb:a3:39:92:06:9f:99:d3:bf:d3:ea:4f:
+ 50:9c:19:fe:96:87:1e:3c:65:f6:a3:18:24:83:86:
+ 10:e7:54:3e:a8:3a:76:24:4f:81:21:c5:e3:0f:02:
+ f8:93:94:47:20:bb:fe:d4:0e:d3:68:b9:dd:c4:7a:
+ 84:82:e3:53:54:79:dd:db:9c:d2:f2:07:9b:2e:b6:
+ bc:3e:ed:85:6d:ef:25:11:f2:97:1a:42:61:f7:4a:
+ 97:e8:8b:b1:10:07:fa:65:81:b2:a2:39:cf:f7:3c:
+ ff:18:fb:c6:f1:5a:8b:59:e2:02:ac:7b:92:d0:4e:
+ 14:4f:59:45:f6:0c:5e:28:5f:b0:e8:3f:45:cf:cf:
+ af:9b:6f:fb:84:d3:77:5a:95:6f:ac:94:84:9e:ee:
+ bc:c0:4a:8f:4a:93:f8:44:21:e2:31:45:61:50:4e:
+ 10:d8:e3:35:7c:4c:19:b4:de:05:bf:a3:06:9f:c8:
+ b5:cd:e4:1f:d7:17:06:0d:7a:95:74:55:0d:68:1a:
+ fc:10:1b:62:64:9d:6d:e0:95:a0:c3:94:07:57:0d:
+ 14:e6:bd:05:fb:b8:9f:e6:df:8b:e2:c6:e7:7e:96:
+ f6:53:c5:80:34:50:28:58:f0:12:50:71:17:30:ba:
+ e6:78:63:bc:f4:b2:ad:9b:2b:b2:fe:e1:39:8c:5e:
+ ba:0b:20:94:de:7b:83:b8:ff:e3:56:8d:b7:11:e9:
+ 3b:8c:f2:b1:c1:5d:9d:a4:0b:4c:2b:d9:b2:18:f5:
+ b5:9f:4b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 0b:7b:72:87:c0:60:a6:49:4c:88:58:e6:1d:88:f7:14:64:48:
+ a6:d8:58:0a:0e:4f:13:35:df:35:1d:d4:ed:06:31:c8:81:3e:
+ 6a:d5:dd:3b:1a:32:ee:90:3d:11:d2:2e:f4:8e:c3:63:2e:23:
+ 66:b0:67:be:6f:b6:c0:13:39:60:aa:a2:34:25:93:75:52:de:
+ a7:9d:ad:0e:87:89:52:71:6a:16:3c:19:1d:83:f8:9a:29:65:
+ be:f4:3f:9a:d9:f0:f3:5a:87:21:71:80:4d:cb:e0:38:9b:3f:
+ bb:fa:e0:30:4d:cf:86:d3:65:10:19:18:d1:97:02:b1:2b:72:
+ 42:68:ac:a0:bd:4e:5a:da:18:bf:6b:98:81:d0:fd:9a:be:5e:
+ 15:48:cd:11:15:b9:c0:29:5c:b4:e8:88:f7:3e:36:ae:b7:62:
+ fd:1e:62:de:70:78:10:1c:48:5b:da:bc:a4:38:ba:67:ed:55:
+ 3e:5e:57:df:d4:03:40:4c:81:a4:d2:4f:63:a7:09:42:09:14:
+ fc:00:a9:c2:80:73:4f:2e:c0:40:d9:11:7b:48:ea:7a:02:c0:
+ d3:eb:28:01:26:58:74:c1:c0:73:22:6d:93:95:fd:39:7d:bb:
+ 2a:e3:f6:82:e3:2c:97:5f:4e:1f:91:94:fa:fe:2c:a3:d8:76:
+ 1a:b8:4d:b2:38:4f:9b:fa:1d:48:60:79:26:e2:f3:fd:a9:d0:
+ 9a:e8:70:8f:49:7a:d6:e5:bd:0a:0e:db:2d:f3:8d:bf:eb:e3:
+ a4:7d:cb:c7:95:71:e8:da:a3:7c:c5:c2:f8:74:92:04:1b:86:
+ ac:a4:22:53:40:b6:ac:fe:4c:76:cf:fb:94:32:c0:35:9f:76:
+ 3f:6e:e5:90:6e:a0:a6:26:a2:b8:2c:be:d1:2b:85:fd:a7:68:
+ c8:ba:01:2b:b1:6c:74:1d:b8:73:95:e7:ee:b7:c7:25:f0:00:
+ 4c:00:b2:7e:b6:0b:8b:1c:f3:c0:50:9e:25:b9:e0:08:de:36:
+ 66:ff:37:a5:d1:bb:54:64:2c:c9:27:b5:4b:92:7e:65:ff:d3:
+ 2d:e1:b9:4e:bc:7f:a4:41:21:90:41:77:a6:39:1f:ea:9e:e3:
+ 9f:d0:66:6f:05:ec:aa:76:7e:bf:6b:16:a0:eb:b5:c7:fc:92:
+ 54:2f:2b:11:27:25:37:78:4c:51:6a:b0:f3:cc:58:5d:14:f1:
+ 6a:48:15:ff:c2:07:b6:b1:8d:0f:8e:5c:50:46:b3:3d:bf:01:
+ 98:4f:b2:59:54:47:3e:34:7b:78:6d:56:93:2e:73:ea:66:28:
+ 78:cd:1d:14:bf:a0:8f:2f:2e:b8:2e:8e:f2:14:8a:cc:e9:b5:
+ 7c:fb:6c:9d:0c:a5:e1:96
+SHA1 Fingerprint=F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC
diff --git a/luni/src/main/files/cacerts/63a2c897.0 b/luni/src/main/files/cacerts/63a2c897.0
new file mode 100644
index 0000000..46f7b14
--- /dev/null
+++ b/luni/src/main/files/cacerts/63a2c897.0
@@ -0,0 +1,119 @@
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw
+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv
+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD
+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F
+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1
+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X
+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+
+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs
+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm
+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe
+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu
+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4
+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs
+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ
+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD
+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG
+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl
+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj
+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed
+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7
+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI
+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7
+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW
+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 95:be:16:a0:f7:2e:46:f1:7b:39:82:72:fa:8b:cd:96
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=TeliaSonera, CN=TeliaSonera Root CA v1
+ Validity
+ Not Before: Oct 18 12:00:50 2007 GMT
+ Not After : Oct 18 12:00:50 2032 GMT
+ Subject: O=TeliaSonera, CN=TeliaSonera Root CA v1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:c2:be:eb:27:f0:21:a3:f3:69:26:55:7e:9d:c5:
+ 55:16:91:5c:fd:ef:21:bf:53:80:7a:2d:d2:91:8c:
+ 63:31:f0:ec:24:f0:c3:a5:d2:72:7c:10:6d:f4:37:
+ b7:e5:e6:7c:79:ea:8c:b5:82:8b:ae:48:b6:ac:00:
+ dc:65:75:ec:2a:4d:5f:c1:87:f5:20:65:2b:81:a8:
+ 47:3e:89:23:95:30:16:90:7f:e8:57:07:48:e7:19:
+ ae:bf:45:67:b1:37:1b:06:2a:fe:de:f9:ac:7d:83:
+ fb:5e:ba:e4:8f:97:67:be:4b:8e:8d:64:07:57:38:
+ 55:69:34:36:3d:13:48:ef:4f:e2:d3:66:1e:a4:cf:
+ 1a:b7:5e:36:33:d4:b4:06:bd:18:01:fd:77:84:50:
+ 00:45:f5:8c:5d:e8:23:bc:7e:fe:35:e1:ed:50:7b:
+ a9:30:8d:19:d3:09:8e:68:67:5d:bf:3c:97:18:53:
+ bb:29:62:c5:ca:5e:72:c1:c7:96:d4:db:2d:a0:b4:
+ 1f:69:03:ec:ea:e2:50:f1:0c:3c:f0:ac:f3:53:2d:
+ f0:1c:f5:ed:6c:39:39:73:80:16:c8:52:b0:23:cd:
+ e0:3e:dc:dd:3c:47:a0:bb:35:8a:e2:98:68:8b:be:
+ e5:bf:72:ee:d2:fa:a5:ed:12:ed:fc:98:18:a9:26:
+ 76:dc:28:4b:10:20:1c:d3:7f:16:77:2d:ed:6f:80:
+ f7:49:bb:53:05:bb:5d:68:c7:d4:c8:75:16:3f:89:
+ 5a:8b:f7:17:47:d4:4c:f1:d2:89:79:3e:4d:3d:98:
+ a8:61:de:3a:1e:d2:f8:5e:03:e0:c1:c9:1c:8c:d3:
+ 8d:4d:d3:95:36:b3:37:5f:63:63:9b:33:14:f0:2d:
+ 26:6b:53:7c:89:8c:32:c2:6e:ec:3d:21:00:39:c9:
+ a1:68:e2:50:83:2e:b0:3a:2b:f3:36:a0:ac:2f:e4:
+ 6f:61:c2:51:09:39:3e:8b:53:b9:bb:67:da:dc:53:
+ b9:76:59:36:9d:43:e5:20:e0:3d:32:60:85:22:51:
+ b7:c7:33:bb:dd:15:2f:a4:78:a6:07:7b:81:46:36:
+ 04:86:dd:79:35:c7:95:2c:3b:b0:a3:17:35:e5:73:
+ 1f:b4:5c:59:ef:da:ea:10:65:7b:7a:d0:7f:9f:b3:
+ b4:2a:37:3b:70:8b:9b:5b:b9:2b:b7:ec:b2:51:12:
+ 97:53:29:5a:d4:f0:12:10:dc:4f:02:bb:12:92:2f:
+ 62:d4:3f:69:43:7c:0d:d6:fc:58:75:01:88:9d:58:
+ 16:4b:de:ba:90:ff:47:01:89:06:6a:f6:5f:b2:90:
+ 6a:b3:02:a6:02:88:bf:b3:47:7e:2a:d9:d5:fa:68:
+ 78:35:4d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ F0:8F:59:38:00:B3:F5:8F:9A:96:0C:D5:EB:FA:7B:AA:17:E8:13:12
+ Signature Algorithm: sha1WithRSAEncryption
+ be:e4:5c:62:4e:24:f4:0c:08:ff:f0:d3:0c:68:e4:93:49:22:
+ 3f:44:27:6f:bb:6d:de:83:66:ce:a8:cc:0d:fc:f5:9a:06:e5:
+ 77:14:91:eb:9d:41:7b:99:2a:84:e5:ff:fc:21:c1:5d:f0:e4:
+ 1f:57:b7:75:a9:a1:5f:02:26:ff:d7:c7:f7:4e:de:4f:f8:f7:
+ 1c:46:c0:7a:4f:40:2c:22:35:f0:19:b1:d0:6b:67:2c:b0:a8:
+ e0:c0:40:37:35:f6:84:5c:5c:e3:af:42:78:fe:a7:c9:0d:50:
+ ea:0d:84:76:f6:51:ef:83:53:c6:7a:ff:0e:56:49:2e:8f:7a:
+ d6:0c:e6:27:54:e3:4d:0a:60:72:62:cd:91:07:d6:a5:bf:c8:
+ 99:6b:ed:c4:19:e6:ab:4c:11:38:c5:6f:31:e2:6e:49:c8:3f:
+ 76:80:26:03:26:29:e0:36:f6:f6:20:53:e3:17:70:34:17:9d:
+ 63:68:1e:6b:ec:c3:4d:86:b8:13:30:2f:5d:46:0d:47:43:d5:
+ 1b:aa:59:0e:b9:5c:8d:06:48:ad:74:87:5f:c7:fc:31:54:41:
+ 13:e2:c7:21:0e:9e:e0:1e:0d:e1:c0:7b:43:85:90:c5:8a:58:
+ c6:65:0a:78:57:f2:c6:23:0f:01:d9:20:4b:de:0f:fb:92:85:
+ 75:2a:5c:73:8d:6d:7b:25:91:ca:ee:45:ae:06:4b:00:cc:d3:
+ b1:59:50:da:3a:88:3b:29:43:46:5e:97:2b:54:ce:53:6f:8d:
+ 4a:e7:96:fa:bf:71:0e:42:8b:7c:fd:28:a0:d0:48:ca:da:c4:
+ 81:4c:bb:a2:73:93:26:c8:eb:0c:d6:26:88:b6:c0:24:cf:bb:
+ bd:5b:eb:75:7d:e9:08:8e:86:33:2c:79:77:09:69:a5:89:fc:
+ b3:70:90:87:76:8f:d3:22:bb:42:ce:bd:73:0b:20:26:2a:d0:
+ 9b:3d:70:1e:24:6c:cd:87:76:a9:17:96:b7:cf:0d:92:fb:8e:
+ 18:a9:98:49:d1:9e:fe:60:44:72:21:b9:19:ed:c2:f5:31:f1:
+ 39:48:88:90:24:75:54:16:ad:ce:f4:f8:69:14:64:39:fb:a3:
+ b8:ba:70:40:c7:27:1c:bf:c4:56:53:fa:63:65:d0:f3:1c:0e:
+ 16:f5:6b:86:58:4d:18:d4:e4:0d:8e:a5:9d:5b:91:dc:76:24:
+ 50:3f:c6:2a:fb:d9:b7:9c:b5:d6:e6:d0:d9:e8:19:8b:15:71:
+ 48:ad:b7:ea:d8:59:88:d4:90:bf:16:b3:d9:e9:ac:59:61:54:
+ c8:1c:ba:ca:c1:ca:e1:b9:20:4c:8f:3a:93:89:a5:a0:cc:bf:
+ d3:f6:75:a4:75:96:6d:56
+SHA1 Fingerprint=43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37
diff --git a/luni/src/main/files/cacerts/8f7b96c4.0 b/luni/src/main/files/cacerts/8f7b96c4.0
deleted file mode 100644
index 33d3474..0000000
--- a/luni/src/main/files/cacerts/8f7b96c4.0
+++ /dev/null
@@ -1,72 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj
-dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0
-NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD
-VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G
-vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/
-BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl
-IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw
-NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq
-y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy
-0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1
-E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 930140085 (0x3770cfb5)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2
- Validity
- Not Before: Jun 23 12:14:45 1999 GMT
- Not After : Jun 23 12:14:45 2019 GMT
- Subject: C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
- Modulus:
- 00:e4:39:39:93:1e:52:06:1b:28:36:f8:b2:a3:29:
- c5:ed:8e:b2:11:bd:fe:eb:e7:b4:74:c2:8f:ff:05:
- e7:d9:9d:06:bf:12:c8:3f:0e:f2:d6:d1:24:b2:11:
- de:d1:73:09:8a:d4:b1:2c:98:09:0d:1e:50:46:b2:
- 83:a6:45:8d:62:68:bb:85:1b:20:70:32:aa:40:cd:
- a6:96:5f:c4:71:37:3f:04:f3:b7:41:24:39:07:1a:
- 1e:2e:61:58:a0:12:0b:e5:a5:df:c5:ab:ea:37:71:
- cc:1c:c8:37:3a:b9:97:52:a7:ac:c5:6a:24:94:4e:
- 9c:7b:cf:c0:6a:d6:df:21:bd
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 CRL Distribution Points:
-
- Full Name:
- DirName: C = US, O = Equifax Secure, OU = Equifax Secure eBusiness CA-2, CN = CRL1
-
- X509v3 Private Key Usage Period:
- Not After: Jun 23 12:14:45 2019 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:50:9E:0B:EA:AF:5E:B9:20:48:A6:50:6A:CB:FD:D8:20:7A:A7:82:76
-
- X509v3 Subject Key Identifier:
- 50:9E:0B:EA:AF:5E:B9:20:48:A6:50:6A:CB:FD:D8:20:7A:A7:82:76
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0...V3.0c....
- Signature Algorithm: sha1WithRSAEncryption
- 0c:86:82:ad:e8:4e:1a:f5:8e:89:27:e2:35:58:3d:29:b4:07:
- 8f:36:50:95:bf:6e:c1:9e:eb:c4:90:b2:85:a8:bb:b7:42:e0:
- 0f:07:39:df:fb:9e:90:b2:d1:c1:3e:53:9f:03:44:b0:7e:4b:
- f4:6f:e4:7c:1f:e7:e2:b1:e4:b8:9a:ef:c3:bd:ce:de:0b:32:
- 34:d9:de:28:ed:33:6b:c4:d4:d7:3d:12:58:ab:7d:09:2d:cb:
- 70:f5:13:8a:94:a1:27:a4:d6:70:c5:6d:94:b5:c9:7d:9d:a0:
- d2:c6:08:49:d9:66:9b:a6:d3:f4:0b:dc:c5:26:57:e1:91:30:
- ea:cd
-SHA1 Fingerprint=39:4F:F6:85:0B:06:BE:52:E5:18:56:CC:10:E1:80:E8:82:B3:85:CC
diff --git a/luni/src/main/files/cacerts/91739615.0 b/luni/src/main/files/cacerts/91739615.0
new file mode 100644
index 0000000..3549e54
--- /dev/null
+++ b/luni/src/main/files/cacerts/91739615.0
@@ -0,0 +1,84 @@
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1
+MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
+czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG
+CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy
+MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl
+ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS
+b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy
+euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO
+bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw
+WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d
+MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE
+1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/
+zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB
+BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF
+BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV
+v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG
+E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
+uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW
+iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v
+GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 54:80:f9:a0:73:ed:3f:00:4c:ca:89:d8:e3:71:e6:4a
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=EE, O=AS Sertifitseerimiskeskus, CN=EE Certification Centre Root CA/emailAddress=pki@sk.ee
+ Validity
+ Not Before: Oct 30 10:10:30 2010 GMT
+ Not After : Dec 17 23:59:59 2030 GMT
+ Subject: C=EE, O=AS Sertifitseerimiskeskus, CN=EE Certification Centre Root CA/emailAddress=pki@sk.ee
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c8:20:c0:ec:e0:c5:4b:ab:07:78:95:f3:44:ee:
+ fb:0b:0c:ff:74:8e:61:bb:b1:62:ea:23:d8:ab:a1:
+ 65:32:7a:eb:8e:17:4f:96:d8:0a:7b:91:a2:63:6c:
+ c7:8c:4c:2e:79:bf:a9:05:fc:69:5c:95:8d:62:f9:
+ b9:70:ed:c3:51:7d:d0:93:e6:6c:eb:30:4b:e1:bc:
+ 7d:bf:52:9b:ce:6e:7b:65:f2:38:b1:c0:a2:32:ef:
+ 62:b2:68:e0:61:53:c1:36:95:ff:ec:94:ba:36:ae:
+ 9c:1c:a7:32:0f:e5:7c:b4:c6:6f:74:fd:7b:18:e8:
+ ac:57:ed:06:20:4b:32:30:58:5b:fd:cd:a8:e6:a1:
+ fc:70:bc:8e:92:73:db:97:a7:7c:21:ae:3d:c1:f5:
+ 48:87:6c:27:bd:9f:25:74:81:55:b0:f7:75:f6:3d:
+ a4:64:6b:d6:4f:e7:ce:40:ad:0f:dd:32:d3:bc:8a:
+ 12:53:98:c9:89:fb:10:1d:4d:7e:cd:7e:1f:56:0d:
+ 21:70:85:f6:20:83:1f:f6:ba:1f:04:8f:ea:77:88:
+ 35:c4:ff:ea:4e:a1:8b:4d:3f:63:1b:44:c3:44:d4:
+ 25:76:ca:b7:8d:d7:1e:4a:66:64:cd:5c:c5:9c:83:
+ e1:c2:08:88:9a:ec:4e:a3:f1:3e:1c:2c:d9:6c:1d:
+ a1:4b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 12:F2:5A:3E:EA:56:1C:BF:CD:06:AC:F1:F1:25:C9:A9:4B:D4:14:99
+ X509v3 Extended Key Usage:
+ TLS Web Client Authentication, TLS Web Server Authentication, Code Signing, E-mail Protection, Time Stamping, OCSP Signing
+ Signature Algorithm: sha1WithRSAEncryption
+ 7b:f6:e4:c0:0d:aa:19:47:b7:4d:57:a3:fe:ad:bb:b1:6a:d5:
+ 0f:9e:db:e4:63:c5:8e:a1:50:56:93:96:b8:38:c0:24:22:66:
+ bc:53:14:61:95:bf:d0:c7:2a:96:39:3f:7d:28:b3:10:40:21:
+ 6a:c4:af:b0:52:77:18:e1:96:d8:56:5d:e3:dd:36:5e:1d:a7:
+ 50:54:a0:c5:2a:e4:aa:8c:94:8a:4f:9d:35:ff:76:a4:06:13:
+ 91:a2:a2:7d:00:44:3f:55:d3:82:3c:1a:d5:5b:bc:56:4c:22:
+ 2e:46:43:8a:24:40:2d:f3:12:b8:3b:70:1a:a4:96:b9:1a:af:
+ 87:41:1a:6a:18:0d:06:4f:c7:3e:6e:b9:29:4d:0d:49:89:11:
+ 87:32:5b:e6:4b:04:c8:e4:5c:e6:74:73:94:5d:16:98:13:95:
+ fe:fb:db:b1:44:e5:3a:70:ac:37:6b:e6:b3:33:72:28:c9:b3:
+ 57:a0:f6:02:16:88:06:0b:b6:a6:4b:20:28:d4:de:3d:8b:ad:
+ 37:05:53:74:fe:6e:cc:bc:43:17:71:5e:f9:c5:cc:1a:a9:61:
+ ee:f7:76:0c:f3:72:f4:72:ad:cf:72:02:36:07:47:cf:ef:19:
+ 50:89:60:cc:e9:24:95:0f:c2:cb:1d:f2:6f:76:90:c7:cc:75:
+ c1:96:c5:9d
+SHA1 Fingerprint=C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7
diff --git a/luni/src/main/files/cacerts/9576d26b.0 b/luni/src/main/files/cacerts/9576d26b.0
new file mode 100644
index 0000000..e77a90c
--- /dev/null
+++ b/luni/src/main/files/cacerts/9576d26b.0
@@ -0,0 +1,119 @@
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 10572350602393338211 (0x92b888dbb08ac163)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R2
+ Validity
+ Not Before: Jul 19 09:15:30 2012 GMT
+ Not After : Jul 19 09:15:30 2042 GMT
+ Subject: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:a2:a3:c4:00:09:d6:85:5d:2d:6d:14:f6:c2:c3:
+ 73:9e:35:c2:71:55:7e:81:fb:ab:46:50:e0:c1:7c:
+ 49:78:e6:ab:79:58:3c:da:ff:7c:1c:9f:d8:97:02:
+ 78:3e:6b:41:04:e9:41:bd:be:03:2c:45:f6:2f:64:
+ d4:ab:5d:a3:47:3d:64:9b:e9:68:9a:c6:cc:1b:3f:
+ ba:be:b2:8b:34:02:2e:98:55:19:fc:8c:6f:aa:5f:
+ da:4c:ce:4d:03:21:a3:d8:d2:34:93:56:96:cb:4c:
+ 0c:00:16:3c:5f:1a:cd:c8:c7:6c:a6:ad:d3:31:a7:
+ bc:e8:e5:e1:66:d6:d2:fb:03:b4:41:65:c9:10:ae:
+ 0e:05:63:c6:80:6a:69:30:fd:d2:ee:90:ef:0d:27:
+ df:9f:95:73:f4:e1:25:da:6c:16:de:41:38:34:ea:
+ 8b:fc:d1:e8:04:14:61:2d:41:7e:ac:c7:77:4e:cb:
+ 51:54:fb:5e:92:18:1b:04:5a:68:c6:c9:c4:fa:b7:
+ 13:a0:98:b7:11:2b:b7:d6:57:cc:7c:9e:17:d1:cb:
+ 25:fe:86:4e:24:2e:56:0c:78:4d:9e:01:12:a6:2b:
+ a7:01:65:6e:7c:62:1d:84:84:df:ea:c0:6b:b5:a5:
+ 2a:95:83:c3:53:11:0c:73:1d:0b:b2:46:90:d1:42:
+ 3a:ce:40:6e:95:ad:ff:c6:94:ad:6e:97:84:8e:7d:
+ 6f:9e:8a:80:0d:49:6d:73:e2:7b:92:1e:c3:f3:c1:
+ f3:eb:2e:05:6f:d9:1b:cf:37:76:04:c8:b4:5a:e4:
+ 17:a7:cb:dd:76:1f:d0:19:76:e8:2c:05:b3:d6:9c:
+ 34:d8:96:dc:61:87:91:05:e4:44:08:33:c1:da:b9:
+ 08:65:d4:ae:b2:36:0d:eb:ba:38:ba:0c:e5:9b:9e:
+ eb:8d:66:dd:99:cf:d6:89:41:f6:04:92:8a:29:29:
+ 6d:6b:3a:1c:e7:75:7d:02:71:0e:f3:c0:e7:bd:cb:
+ 19:dd:9d:60:b2:c2:66:60:b6:b1:04:ee:c9:e6:86:
+ b9:9a:66:40:a8:e7:11:ed:81:45:03:8b:f6:67:59:
+ e8:c1:06:11:bd:dd:cf:80:02:4f:65:40:78:5c:47:
+ 50:c8:9b:e6:1f:81:7b:e4:44:a8:5b:85:9a:e2:de:
+ 5a:d5:c7:f9:3a:44:66:4b:e4:32:54:7c:e4:6c:9c:
+ b3:0e:3d:17:a2:b2:34:12:d6:7e:b2:a8:49:bb:d1:
+ 7a:28:40:be:a2:16:1f:df:e4:37:1f:11:73:fb:90:
+ 0a:65:43:a2:0d:7c:f8:06:01:55:33:7d:b0:0d:b8:
+ f4:f5:ae:a5:42:57:7c:36:11:8c:7b:5e:c4:03:9d:
+ 8c:79:9d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ B5:99:F8:AF:B0:94:F5:E3:20:D6:0A:AD:CE:4E:56:A4:2E:6E:42:ED
+ Signature Algorithm: sha256WithRSAEncryption
+ 26:06:5e:70:e7:65:33:c8:82:6e:d9:9c:17:3a:1b:7a:66:b2:
+ 01:f6:78:3b:69:5e:2f:ea:ff:4e:f9:28:c3:98:2a:61:4c:b4:
+ 24:12:8a:7d:6d:11:14:f7:9c:b5:ca:e6:bc:9e:27:8e:4c:19:
+ c8:a9:bd:7a:c0:d7:36:0e:6d:85:72:6e:a8:c6:a2:6d:f6:fa:
+ 73:63:7f:bc:6e:79:08:1c:9d:8a:9f:1a:8a:53:a6:d8:bb:d9:
+ 35:55:b1:11:c5:a9:03:b3:56:3b:b9:84:93:22:5e:7e:c1:f6:
+ 12:52:8b:ea:2c:67:bc:fe:36:4c:f5:b8:cf:d1:b3:49:92:3b:
+ d3:29:0e:99:1b:96:f7:61:b8:3b:c4:2b:b6:78:6c:b4:23:6f:
+ f0:fd:d3:b2:5e:75:1f:99:95:a8:ac:f6:da:e1:c5:31:7b:fb:
+ d1:46:b3:d2:bc:67:b4:62:54:ba:09:f7:63:b0:93:a2:9a:f9:
+ e9:52:2e:8b:60:12:ab:fc:f5:60:56:ef:10:5c:8b:c4:1a:42:
+ dc:83:5b:64:0e:cb:b5:bc:d6:4f:c1:7c:3c:6e:8d:13:6d:fb:
+ 7b:eb:30:d0:dc:4d:af:c5:d5:b6:a5:4c:5b:71:c9:e8:31:be:
+ e8:38:06:48:a1:1a:e2:ea:d2:de:12:39:58:1a:ff:80:0e:82:
+ 75:e6:b7:c9:07:6c:0e:ef:ff:38:f1:98:71:c4:b7:7f:0e:15:
+ d0:25:69:bd:22:9d:2b:ed:05:f6:46:47:ac:ed:c0:f0:d4:3b:
+ e2:ec:ee:96:5b:90:13:4e:1e:56:3a:eb:b0:ef:96:bb:96:23:
+ 11:ba:f2:43:86:74:64:95:c8:28:75:df:1d:35:ba:d2:37:83:
+ 38:53:38:36:3b:cf:6c:e9:f9:6b:0e:d0:fb:04:e8:4f:77:d7:
+ 65:01:78:86:0c:7a:3e:21:62:f1:7f:63:71:0c:c9:9f:44:db:
+ a8:27:a2:75:be:6e:81:3e:d7:c0:eb:1b:98:0f:70:5c:34:b2:
+ 8a:cc:c0:85:18:eb:6e:7a:b3:f7:5a:a1:07:bf:a9:42:92:f3:
+ 60:22:97:e4:14:a1:07:9b:4e:76:c0:8e:7d:fd:a4:25:c7:47:
+ ed:ff:1f:73:ac:cc:c3:a5:e9:6f:0a:8e:9b:65:c2:50:85:b5:
+ a3:a0:53:12:cc:55:87:61:f3:81:ae:10:46:61:bd:44:21:b8:
+ c2:3d:74:cf:7e:24:35:fa:1c:07:0e:9b:3d:22:ca:ef:31:2f:
+ 8c:ac:12:bd:ef:40:28:fc:29:67:9f:b2:13:4f:66:24:c4:53:
+ 19:e9:1e:29:15:ef:e6:6d:b0:7f:2d:67:fd:f3:6c:1b:75:46:
+ a3:e5:4a:17:e9:a4:d7:0b
+SHA1 Fingerprint=B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71
diff --git a/luni/src/main/files/cacerts/9ab62355.0 b/luni/src/main/files/cacerts/9ab62355.0
new file mode 100644
index 0000000..1de7078
--- /dev/null
+++ b/luni/src/main/files/cacerts/9ab62355.0
@@ -0,0 +1,128 @@
+-----BEGIN CERTIFICATE-----
+MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw
+ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp
+dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290
+IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD
+VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy
+dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg
+MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx
+UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD
+1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH
+oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR
+HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/
+5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv
+idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL
+OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC
+NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f
+46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB
+UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth
+7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G
+A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED
+MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB
+bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x
+XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T
+PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0
+Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70
+WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL
+Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm
+7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S
+nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN
+vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB
+WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI
+fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb
+I+2ksx0WckNLIOFZfsLorSa/ovc=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ f2:fa:64:e2:74:63:d3:8d:fd:10:1d:04:1f:76:ca:58
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=ch, O=Swisscom, OU=Digital Certificate Services, CN=Swisscom Root EV CA 2
+ Validity
+ Not Before: Jun 24 09:45:08 2011 GMT
+ Not After : Jun 25 08:45:08 2031 GMT
+ Subject: C=ch, O=Swisscom, OU=Digital Certificate Services, CN=Swisscom Root EV CA 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:c4:f7:1d:2f:57:ea:57:6c:f7:70:5d:63:b0:71:
+ 52:09:60:44:28:33:a3:7a:4e:0a:fa:d8:ea:6c:8b:
+ 51:16:1a:55:ae:54:26:c4:cc:45:07:41:4f:10:79:
+ 7f:71:d2:7a:4e:3f:38:4e:b3:00:c6:95:ca:5b:cd:
+ c1:2a:83:d7:27:1f:31:0e:23:16:b7:25:cb:1c:b4:
+ b9:80:32:5e:1a:9d:93:f1:e8:3c:60:2c:a7:5e:57:
+ 19:58:51:5e:bc:2c:56:0b:b8:d8:ef:8b:82:b4:3c:
+ b8:c2:24:a8:13:c7:a0:21:36:1b:7a:57:29:28:a7:
+ 2e:bf:71:25:90:f3:44:83:69:50:a4:e4:e1:1b:62:
+ 19:94:09:a3:f3:c3:bc:ef:f4:bd:ec:db:13:9d:cf:
+ 9d:48:09:52:67:c0:37:29:11:1e:fb:d2:11:a7:85:
+ 18:74:79:e4:4f:85:14:eb:52:37:e2:b1:45:d8:cc:
+ 0d:43:7f:ae:13:d2:6b:2b:3f:a7:c2:e2:a8:6d:76:
+ 5b:43:9f:be:b4:9d:b3:26:86:3b:1f:7f:e5:f2:e8:
+ 66:28:16:25:d0:4b:97:38:a7:e4:cf:09:d1:36:c3:
+ 0b:be:da:3b:44:58:8d:be:f1:9e:09:6b:3e:f3:32:
+ c7:2b:87:c6:ec:5e:9c:f6:87:65:ad:33:29:c4:2f:
+ 89:d9:b9:cb:c9:03:9d:fb:6c:94:51:97:10:1b:86:
+ 0b:1a:1b:3f:f6:02:7e:7b:d4:c5:51:64:28:9d:f5:
+ d3:ac:83:81:88:d3:74:b4:59:9d:c1:eb:61:33:5a:
+ 45:d1:cb:39:d0:06:6a:53:60:1d:af:f6:fb:69:bc:
+ 6a:dc:01:cf:bd:f9:8f:d9:bd:5b:c1:3a:5f:8e:da:
+ 0f:4b:a9:9b:9d:2a:28:6b:1a:0a:7c:3c:ab:22:0b:
+ e5:77:2d:71:f6:82:35:81:ae:f8:7b:81:e6:ea:fe:
+ ac:f4:1a:9b:74:5c:e8:8f:24:f6:5d:9d:46:c4:2c:
+ d2:1e:2b:21:6a:83:27:67:55:4a:a4:e3:c8:32:97:
+ 66:90:72:da:e3:d4:64:2e:5f:e3:a1:6a:f6:60:d4:
+ e7:35:cd:ca:c4:68:8d:d7:71:c8:d3:24:33:73:b1:
+ 6c:f9:6a:e1:28:db:5f:c6:3d:e8:be:55:e6:37:1b:
+ ed:24:d9:0f:19:8f:5f:63:18:58:50:81:51:65:6f:
+ f2:9f:7e:6a:04:e7:34:24:71:ba:76:4b:58:1e:19:
+ bd:15:60:45:aa:0c:12:40:01:9d:10:e2:c7:38:07:
+ 72:0a:65:c0:b6:bb:25:29:da:16:9e:8b:35:8b:61:
+ ed:e5:71:57:83:b5:3c:71:9f:e3:4f:bf:7e:1e:81:
+ 9f:41:97
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Policy Mappings:
+ 2.16.756.1.83.2.2:2.16.756.1.83.2.2
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:3
+ X509v3 Subject Key Identifier:
+ 45:D9:A5:81:6E:3D:88:4D:8D:71:D2:46:C1:6E:45:1E:F3:C4:80:9D
+ X509v3 Authority Key Identifier:
+ keyid:45:D9:A5:81:6E:3D:88:4D:8D:71:D2:46:C1:6E:45:1E:F3:C4:80:9D
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 94:3a:73:06:9f:52:4b:30:5c:d4:fe:b1:5c:25:f9:d7:8e:6f:
+ f5:87:64:9f:ed:14:8e:b8:04:8e:28:4b:8f:aa:7b:8e:39:b4:
+ d9:58:f6:7b:a1:35:0a:a1:9d:8a:f7:63:e5:eb:bd:39:82:d4:
+ e3:7a:2d:6f:df:13:3c:ba:fe:7e:56:98:0b:f3:54:9f:cd:44:
+ 4e:6e:3c:e1:3e:15:bf:06:26:9d:e4:f0:90:b6:d4:c2:9e:30:
+ 2e:1f:ef:c7:7a:c4:50:c7:ea:7b:da:50:cb:7a:26:cb:00:b4:
+ 5a:ab:b5:93:1f:80:89:84:04:95:8d:8d:7f:09:93:bf:d4:a8:
+ a8:e4:63:6d:d9:64:e4:b8:29:5a:08:bf:50:e1:84:0f:55:7b:
+ 5f:08:22:1b:f5:bd:99:1e:14:f6:ce:f4:58:10:82:b3:0a:3d:
+ 19:c1:bf:5b:ab:aa:99:d8:f2:31:bd:e5:38:66:dc:58:05:c7:
+ ed:63:1a:2e:0a:97:7c:87:93:2b:b2:8a:e3:f1:ec:18:e5:75:
+ b6:29:87:e7:dc:8b:1a:7e:b4:d8:c9:d3:8a:17:6c:7d:29:44:
+ be:8a:aa:f5:7e:3a:2e:68:31:93:b9:6a:da:9a:e0:db:e9:2e:
+ a5:84:cd:1c:0a:b8:4a:08:f9:9c:f1:61:26:98:93:b7:7b:66:
+ ec:91:5e:dd:51:3f:db:73:0f:ad:04:58:09:dd:04:02:95:0a:
+ 3e:d3:76:df:a6:10:1e:80:3d:e8:cd:a4:64:d1:33:c7:92:c7:
+ e2:4e:44:e3:09:c9:4e:c2:5d:87:0e:12:9e:bf:0f:c9:05:10:
+ de:7a:a3:b1:3c:f2:3f:a5:aa:27:79:ad:31:7d:1f:fd:fc:19:
+ 69:c5:dd:b9:3f:7c:cd:c6:b4:c2:30:1e:7e:6e:92:d7:7f:61:
+ 76:5a:8f:eb:95:4d:bc:11:6e:21:7c:59:37:99:d0:06:bc:f9:
+ 06:6d:32:16:a5:d9:69:a8:e1:dc:3c:80:1e:60:51:dc:d7:54:
+ 21:1e:ca:62:77:4f:fa:d8:8f:b3:2b:3a:0d:78:72:c9:68:41:
+ 5a:47:4a:c2:a3:eb:1a:d7:0a:ab:3c:32:55:c8:0a:11:9c:df:
+ 74:d6:f0:40:15:1d:c8:b9:8f:b5:36:c5:af:f8:22:b8:ca:1d:
+ f3:d6:b6:19:0f:9f:61:65:6a:ea:74:c8:7c:8f:c3:4f:5d:65:
+ 82:1f:d9:0d:89:da:75:72:fb:ef:f1:47:67:13:b3:c8:d1:19:
+ 88:27:26:9a:99:79:7f:1e:e4:2c:3f:7b:ee:f1:de:4d:8b:96:
+ 97:c3:d5:3f:7c:1b:23:ed:a4:b3:1d:16:72:43:4b:20:e1:59:
+ 7e:c2:e8:ad:26:bf:a2:f7
+SHA1 Fingerprint=E7:A1:90:29:D3:D5:52:DC:0D:0F:C6:92:D3:EA:88:0D:15:2E:1A:6B
diff --git a/luni/src/main/files/cacerts/a15b3b6b.0 b/luni/src/main/files/cacerts/a15b3b6b.0
deleted file mode 100644
index 9ccbc2a..0000000
--- a/luni/src/main/files/cacerts/a15b3b6b.0
+++ /dev/null
@@ -1,75 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
-EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ
-BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
-ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/
-k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso
-LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o
-TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG
-SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
-JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
-RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3
-MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C
-TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5
-WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
-SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR
-xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL
-B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 913232846 (0x366ed3ce)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E2
- Validity
- Not Before: Dec 9 19:17:26 1998 GMT
- Not After : Dec 9 19:47:26 2018 GMT
- Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E2
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
- Modulus:
- 00:bf:93:8f:17:92:ef:33:13:18:eb:10:7f:4e:16:
- bf:ff:06:8f:2a:85:bc:5e:f9:24:a6:24:88:b6:03:
- b7:c1:c3:5f:03:5b:d1:6f:ae:7e:42:ea:66:23:b8:
- 63:83:56:fb:28:2d:e1:38:8b:b4:ee:a8:01:e1:ce:
- 1c:b6:88:2a:22:46:85:fb:9f:a7:70:a9:47:14:3f:
- ce:de:65:f0:a8:71:f7:4f:26:6c:8c:bc:c6:b5:ef:
- de:49:27:ff:48:2a:7d:e8:4d:03:cc:c7:b2:52:c6:
- 17:31:13:3b:b5:4d:db:c8:c4:f6:c3:0f:24:2a:da:
- 0c:9d:e7:91:5b:80:cd:94:9d
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
-
- Full Name:
- DirName: C = US, O = Digital Signature Trust Co., OU = DSTCA E2, CN = CRL1
-
- X509v3 Private Key Usage Period:
- Not Before: Dec 9 19:17:26 1998 GMT, Not After: Dec 9 19:17:26 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B
-
- X509v3 Subject Key Identifier:
- 1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 47:8d:83:ad:62:f2:db:b0:9e:45:22:05:b9:a2:d6:03:0e:38:
- 72:e7:9e:fc:7b:e6:93:b6:9a:a5:a2:94:c8:34:1d:91:d1:c5:
- d7:f4:0a:25:0f:3d:78:81:9e:0f:b1:67:c4:90:4c:63:dd:5e:
- a7:e2:ba:9f:f5:f7:4d:a5:31:7b:9c:29:2d:4c:fe:64:3e:ec:
- b6:53:fe:ea:9b:ed:82:db:74:75:4b:07:79:6e:1e:d8:19:83:
- 73:de:f5:3e:d0:b5:de:e7:4b:68:7d:43:2e:2a:20:e1:7e:a0:
- 78:44:9e:08:f5:98:f9:c7:7f:1b:1b:d6:06:20:02:58:a1:c3:
- a2:03
-SHA1 Fingerprint=AB:48:F3:33:DB:04:AB:B9:C0:72:DA:5B:0C:C1:D0:57:F0:36:9B:46
diff --git a/luni/src/main/files/cacerts/a2df7ad7.0 b/luni/src/main/files/cacerts/a2df7ad7.0
new file mode 100644
index 0000000..da5a4d0
--- /dev/null
+++ b/luni/src/main/files/cacerts/a2df7ad7.0
@@ -0,0 +1,86 @@
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx
+MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB
+ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV
+BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV
+6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX
+GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP
+dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH
+1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF
+62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW
+BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL
+MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU
+cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv
+b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6
+IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/
+iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
+GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh
+4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm
+XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Public CA Root
+ Validity
+ Not Before: May 30 10:41:50 2000 GMT
+ Not After : May 30 10:41:50 2020 GMT
+ Subject: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Public CA Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:e9:1a:30:8f:83:88:14:c1:20:d8:3c:9b:8f:1b:
+ 7e:03:74:bb:da:69:d3:46:a5:f8:8e:c2:0c:11:90:
+ 51:a5:2f:66:54:40:55:ea:db:1f:4a:56:ee:9f:23:
+ 6e:f4:39:cb:a1:b9:6f:f2:7e:f9:5d:87:26:61:9e:
+ 1c:f8:e2:ec:a6:81:f8:21:c5:24:cc:11:0c:3f:db:
+ 26:72:7a:c7:01:97:07:17:f9:d7:18:2c:30:7d:0e:
+ 7a:1e:62:1e:c6:4b:c0:fd:7d:62:77:d3:44:1e:27:
+ f6:3f:4b:44:b3:b7:38:d9:39:1f:60:d5:51:92:73:
+ 03:b4:00:69:e3:f3:14:4e:ee:d1:dc:09:cf:77:34:
+ 46:50:b0:f8:11:f2:fe:38:79:f7:07:39:fe:51:92:
+ 97:0b:5b:08:5f:34:86:01:ad:88:97:eb:66:cd:5e:
+ d1:ff:dc:7d:f2:84:da:ba:77:ad:dc:80:08:c7:a7:
+ 87:d6:55:9f:97:6a:e8:c8:11:64:ba:e7:19:29:3f:
+ 11:b3:78:90:84:20:52:5b:11:ef:78:d0:83:f6:d5:
+ 48:90:d0:30:1c:cf:80:f9:60:fe:79:e4:88:f2:dd:
+ 00:eb:94:45:eb:65:94:69:40:ba:c0:d5:b4:b8:ba:
+ 7d:04:11:a8:eb:31:05:96:94:4e:58:21:8e:9f:d0:
+ 60:fd
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 81:3E:37:D8:92:B0:1F:77:9F:5C:B4:AB:73:AA:E7:F6:34:60:2F:FA
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:81:3E:37:D8:92:B0:1F:77:9F:5C:B4:AB:73:AA:E7:F6:34:60:2F:FA
+ DirName:/C=SE/O=AddTrust AB/OU=AddTrust TTP Network/CN=AddTrust Public CA Root
+ serial:01
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 03:f7:15:4a:f8:24:da:23:56:16:93:76:dd:36:28:b9:ae:1b:
+ b8:c3:f1:64:ba:20:18:78:95:29:27:57:05:bc:7c:2a:f4:b9:
+ 51:55:da:87:02:de:0f:16:17:31:f8:aa:79:2e:09:13:bb:af:
+ b2:20:19:12:e5:93:f9:4b:f9:83:e8:44:d5:b2:41:25:bf:88:
+ 75:6f:ff:10:fc:4a:54:d0:5f:f0:fa:ef:36:73:7d:1b:36:45:
+ c6:21:6d:b4:15:b8:4e:cf:9c:5c:a5:3d:5a:00:8e:06:e3:3c:
+ 6b:32:7b:f2:9f:f0:b6:fd:df:f0:28:18:48:f0:c6:bc:d0:bf:
+ 34:80:96:c2:4a:b1:6d:8e:c7:90:45:de:2f:67:ac:45:04:a3:
+ 7a:dc:55:92:c9:47:66:d8:1a:8c:c7:ed:9c:4e:9a:e0:12:bb:
+ b5:6a:4c:84:e1:e1:22:0d:87:00:64:fe:8c:7d:62:39:65:a6:
+ ef:42:b6:80:25:12:61:01:a8:24:13:70:00:11:26:5f:fa:35:
+ 50:c5:48:cc:06:47:e8:27:d8:70:8d:5f:64:e6:a1:44:26:5e:
+ 22:ec:92:cd:ff:42:9a:44:21:6d:5c:c5:e3:22:1d:5f:47:12:
+ e7:ce:5f:5d:fa:d8:aa:b1:33:2d:d9:76:f2:4e:3a:33:0c:2b:
+ b3:2d:90:06
+SHA1 Fingerprint=2A:B6:28:48:5E:78:FB:F3:AD:9E:79:10:DD:6B:DF:99:72:2C:96:E5
diff --git a/luni/src/main/files/cacerts/b0ed035a.0 b/luni/src/main/files/cacerts/b0ed035a.0
new file mode 100644
index 0000000..b06f963
--- /dev/null
+++ b/luni/src/main/files/cacerts/b0ed035a.0
@@ -0,0 +1,117 @@
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx
+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT
+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5
+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT
+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF
+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz
+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh
+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH
+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc
+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2
+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi
+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP
+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA
+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE
+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm
+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL
+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF
+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo
+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+
+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh
+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW
+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW
+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j
+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz
+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy
+KwbQBM0=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3262 (0xcbe)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA
+ Validity
+ Not Before: Jun 27 06:28:33 2012 GMT
+ Not After : Dec 31 15:59:59 2030 GMT
+ Subject: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:b0:05:db:c8:eb:8c:c4:6e:8a:21:ef:8e:4d:9c:
+ 71:0a:1f:52:70:ed:6d:82:9c:97:c5:d7:4c:4e:45:
+ 49:cb:40:42:b5:12:34:6c:19:c2:74:a4:31:5f:85:
+ 02:97:ec:43:33:0a:53:d2:9c:8c:8e:b7:b8:79:db:
+ 2b:d5:6a:f2:8e:66:c4:ee:2b:01:07:92:d4:b3:d0:
+ 02:df:50:f6:55:af:66:0e:cb:e0:47:60:2f:2b:32:
+ 39:35:52:3a:28:83:f8:7b:16:c6:18:b8:62:d6:47:
+ 25:91:ce:f0:19:12:4d:ad:63:f5:d3:3f:75:5f:29:
+ f0:a1:30:1c:2a:a0:98:a6:15:bd:ee:fd:19:36:f0:
+ e2:91:43:8f:fa:ca:d6:10:27:49:4c:ef:dd:c1:f1:
+ 85:70:9b:ca:ea:a8:5a:43:fc:6d:86:6f:73:e9:37:
+ 45:a9:f0:36:c7:cc:88:75:1e:bb:6c:06:ff:9b:6b:
+ 3e:17:ec:61:aa:71:7c:c6:1d:a2:f7:49:e9:15:b5:
+ 3c:d6:a1:61:f5:11:f7:05:6f:1d:fd:11:be:d0:30:
+ 07:c2:29:b0:09:4e:26:dc:e3:a2:a8:91:6a:1f:c2:
+ 91:45:88:5c:e5:98:b8:71:a5:15:19:c9:7c:75:11:
+ cc:70:74:4f:2d:9b:1d:91:44:fd:56:28:a0:fe:bb:
+ 86:6a:c8:fa:5c:0b:58:dc:c6:4b:76:c8:ab:22:d9:
+ 73:0f:a5:f4:5a:02:89:3f:4f:9e:22:82:ee:a2:74:
+ 53:2a:3d:53:27:69:1d:6c:8e:32:2c:64:00:26:63:
+ 61:36:4e:a3:46:b7:3f:7d:b3:2d:ac:6d:90:a2:95:
+ a2:ce:cf:da:82:e7:07:34:19:96:e9:b8:21:aa:29:
+ 7e:a6:38:be:8e:29:4a:21:66:79:1f:b3:c3:b5:09:
+ 67:de:d6:d4:07:46:f3:2a:da:e6:22:37:60:cb:81:
+ b6:0f:a0:0f:e9:c8:95:7f:bf:55:91:05:7a:cf:3d:
+ 15:c0:6f:de:09:94:01:83:d7:34:1b:cc:40:a5:f0:
+ b8:9b:67:d5:98:91:3b:a7:84:78:95:26:a4:5a:08:
+ f8:2b:74:b4:00:04:3c:df:b8:14:8e:e8:df:a9:8d:
+ 6c:67:92:33:1d:c0:b7:d2:ec:92:c8:be:09:bf:2c:
+ 29:05:6f:02:6b:9e:ef:bc:bf:2a:bc:5b:c0:50:8f:
+ 41:70:71:87:b2:4d:b7:04:a9:84:a3:32:af:ae:ee:
+ 6b:17:8b:b2:b1:fe:6c:e1:90:8c:88:a8:97:48:ce:
+ c8:4d:cb:f3:06:cf:5f:6a:0a:42:b1:1e:1e:77:2f:
+ 8e:a0:e6:92:0e:06:fc:05:22:d2:26:e1:31:51:7d:
+ 32:dc:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 5f:34:81:76:ef:96:1d:d5:e5:b5:d9:02:63:84:16:c1:ae:a0:
+ 70:51:a7:f7:4c:47:35:c8:0b:d7:28:3d:89:71:d9:aa:33:41:
+ ea:14:1b:6c:21:00:c0:6c:42:19:7e:9f:69:5b:20:42:df:a2:
+ d2:da:c4:7c:97:4b:8d:b0:e8:ac:c8:ee:a5:69:04:99:0a:92:
+ a6:ab:27:2e:1a:4d:81:bf:84:d4:70:1e:ad:47:fe:fd:4a:9d:
+ 33:e0:f2:b9:c4:45:08:21:0a:da:69:69:73:72:0d:be:34:fe:
+ 94:8b:ad:c3:1e:35:d7:a2:83:ef:e5:38:c7:a5:85:1f:ab:cf:
+ 34:ec:3f:28:fe:0c:f1:57:86:4e:c9:55:f7:1c:d4:d8:a5:7d:
+ 06:7a:6f:d5:df:10:df:81:4e:21:65:b1:b6:e1:17:79:95:45:
+ 06:ce:5f:cc:dc:46:89:63:68:44:8d:93:f4:64:70:a0:3d:9d:
+ 28:05:c3:39:70:b8:62:7b:20:fd:e4:db:e9:08:a1:b8:9e:3d:
+ 09:c7:4f:fb:2c:f8:93:76:41:de:52:e0:e1:57:d2:9d:03:bc:
+ 77:9e:fe:9e:29:5e:f7:c1:51:60:1f:de:da:0b:b2:2d:75:b7:
+ 43:48:93:e7:f6:79:c6:84:5d:80:59:60:94:fc:78:98:8f:3c:
+ 93:51:ed:40:90:07:df:64:63:24:cb:4e:71:05:a1:d7:94:1a:
+ 88:32:f1:22:74:22:ae:a5:a6:d8:12:69:4c:60:a3:02:ee:2b:
+ ec:d4:63:92:0b:5e:be:2f:76:6b:a3:b6:26:bc:8f:03:d8:0a:
+ f2:4c:64:46:bd:39:62:e5:96:eb:34:63:11:28:cc:95:f1:ad:
+ ef:ef:dc:80:58:48:e9:4b:b8:ea:65:ac:e9:fc:80:b5:b5:c8:
+ 45:f9:ac:c1:9f:d9:b9:ea:62:88:8e:c4:f1:4b:83:12:ad:e6:
+ 8b:84:d6:9e:c2:eb:83:18:9f:6a:bb:1b:24:60:33:70:cc:ec:
+ f7:32:f3:5c:d9:79:7d:ef:9e:a4:fe:c9:23:c3:24:ee:15:92:
+ b1:3d:91:4f:26:86:bd:66:73:24:13:ea:a4:ae:63:c1:ad:7d:
+ 84:03:3c:10:78:86:1b:79:e3:c4:f3:f2:04:95:20:ae:23:82:
+ c4:b3:3a:00:62:bf:e6:36:24:e1:57:ba:c7:1e:90:75:d5:5f:
+ 3f:95:61:2b:c1:3b:cd:e5:b3:68:61:d0:46:26:a9:21:52:69:
+ 2d:eb:2e:c7:eb:77:ce:a6:3a:b5:03:33:4f:76:d1:e7:5c:54:
+ 01:5d:cb:78:f4:c9:0c:bf:cf:12:8e:17:2d:23:68:94:e7:ab:
+ fe:a9:b2:2b:06:d0:04:cd
+SHA1 Fingerprint=9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65
diff --git a/luni/src/main/files/cacerts/b3fb433b.0 b/luni/src/main/files/cacerts/b3fb433b.0
new file mode 100644
index 0000000..de880c1
--- /dev/null
+++ b/luni/src/main/files/cacerts/b3fb433b.0
@@ -0,0 +1,56 @@
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ a6:8b:79:29:00:00:00:00:50:d0:91:f9
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2012 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - EC1
+ Validity
+ Not Before: Dec 18 15:25:36 2012 GMT
+ Not After : Dec 18 15:55:36 2037 GMT
+ Subject: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2012 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - EC1
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:84:13:c9:d0:ba:6d:41:7b:e2:6c:d0:eb:55:5f:
+ 66:02:1a:24:f4:5b:89:69:47:e3:b8:c2:7d:f1:f2:
+ 02:c5:9f:a0:f6:5b:d5:8b:06:19:86:4f:53:10:6d:
+ 07:24:27:a1:a0:f8:d5:47:19:61:4c:7d:ca:93:27:
+ ea:74:0c:ef:6f:96:09:fe:63:ec:70:5d:36:ad:67:
+ 77:ae:c9:9d:7c:55:44:3a:a2:63:51:1f:f5:e3:62:
+ d4:a9:47:07:3e:cc:20
+ ASN1 OID: secp384r1
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ B7:63:E7:1A:DD:8D:E9:08:A6:55:83:A4:E0:6A:50:41:65:11:42:49
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:64:02:30:61:79:d8:e5:42:47:df:1c:ae:53:99:17:b6:6f:
+ 1c:7d:e1:bf:11:94:d1:03:88:75:e4:8d:89:a4:8a:77:46:de:
+ 6d:61:ef:02:f5:fb:b5:df:cc:fe:4e:ff:fe:a9:e6:a7:02:30:
+ 5b:99:d7:85:37:06:b5:7b:08:fd:eb:27:8b:4a:94:f9:e1:fa:
+ a7:8e:26:08:e8:7c:92:68:6d:73:d8:6f:26:ac:21:02:b8:99:
+ b7:26:41:5b:25:60:ae:d0:48:1a:ee:06
+SHA1 Fingerprint=20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47
diff --git a/luni/src/main/files/cacerts/b872f2b4.0 b/luni/src/main/files/cacerts/b872f2b4.0
new file mode 100644
index 0000000..e99bbe9
--- /dev/null
+++ b/luni/src/main/files/cacerts/b872f2b4.0
@@ -0,0 +1,84 @@
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6643877497813316402 (0x5c33cb622c5fb332)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Atos TrustedRoot 2011, O=Atos, C=DE
+ Validity
+ Not Before: Jul 7 14:58:30 2011 GMT
+ Not After : Dec 31 23:59:59 2030 GMT
+ Subject: CN=Atos TrustedRoot 2011, O=Atos, C=DE
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:95:85:3b:97:6f:2a:3b:2e:3b:cf:a6:f3:29:35:
+ be:cf:18:ac:3e:aa:d9:f8:4d:a0:3e:1a:47:b9:bc:
+ 9a:df:f2:fe:cc:3e:47:e8:7a:96:c2:24:8e:35:f4:
+ a9:0c:fc:82:fd:6d:c1:72:62:27:bd:ea:6b:eb:e7:
+ 8a:cc:54:3e:90:50:cf:80:d4:95:fb:e8:b5:82:d4:
+ 14:c5:b6:a9:55:25:57:db:b1:50:f6:b0:60:64:59:
+ 7a:69:cf:03:b7:6f:0d:be:ca:3e:6f:74:72:ea:aa:
+ 30:2a:73:62:be:49:91:61:c8:11:fe:0e:03:2a:f7:
+ 6a:20:dc:02:15:0d:5e:15:6a:fc:e3:82:c1:b5:c5:
+ 9d:64:09:6c:a3:59:98:07:27:c7:1b:96:2b:61:74:
+ 71:6c:43:f1:f7:35:89:10:e0:9e:ec:55:a1:37:22:
+ a2:87:04:05:2c:47:7d:b4:1c:b9:62:29:66:28:ca:
+ b7:e1:93:f5:a4:94:03:99:b9:70:85:b5:e6:48:ea:
+ 8d:50:fc:d9:de:cc:6f:07:0e:dd:0b:72:9d:80:30:
+ 16:07:95:3f:28:0e:fd:c5:75:4f:53:d6:74:9a:b4:
+ 24:2e:8e:02:91:cf:76:c5:9b:1e:55:74:9c:78:21:
+ b1:f0:2d:f1:0b:9f:c2:d5:96:18:1f:f0:54:22:7a:
+ 8c:07
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21
+
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6189.3.4.1.1
+
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 26:77:34:db:94:48:86:2a:41:9d:2c:3e:06:90:60:c4:8c:ac:
+ 0b:54:b8:1f:b9:7b:d3:07:39:e4:fa:3e:7b:b2:3d:4e:ed:9f:
+ 23:bd:97:f3:6b:5c:ef:ee:fd:40:a6:df:a1:93:a1:0a:86:ac:
+ ef:20:d0:79:01:bd:78:f7:19:d8:24:31:34:04:01:a6:ba:15:
+ 9a:c3:27:dc:d8:4f:0f:cc:18:63:ff:99:0f:0e:91:6b:75:16:
+ e1:21:fc:d8:26:c7:47:b7:a6:cf:58:72:71:7e:ba:e1:4d:95:
+ 47:3b:c9:af:6d:a1:b4:c1:ec:89:f6:b4:0f:38:b5:e2:64:dc:
+ 25:cf:a6:db:eb:9a:5c:99:a1:c5:08:de:fd:e6:da:d5:d6:5a:
+ 45:0c:c4:b7:c2:b5:14:ef:b4:11:ff:0e:15:b5:f5:f5:db:c6:
+ bd:eb:5a:a7:f0:56:22:a9:3c:65:54:c6:15:a8:bd:86:9e:cd:
+ 83:96:68:7a:71:81:89:e1:0b:e1:ea:11:1b:68:08:cc:69:9e:
+ ec:9e:41:9e:44:32:26:7a:e2:87:0a:71:3d:eb:e4:5a:a4:d2:
+ db:c5:cd:c6:de:60:7f:b9:f3:4f:44:92:ef:2a:b7:18:3e:a7:
+ 19:d9:0b:7d:b1:37:41:42:b0:ba:60:1d:f2:fe:09:11:b0:f0:
+ 87:7b:a7:9d
+SHA1 Fingerprint=2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21
diff --git a/luni/src/main/files/cacerts/c215bc69.0 b/luni/src/main/files/cacerts/c215bc69.0
deleted file mode 100644
index 5b4f82f..0000000
--- a/luni/src/main/files/cacerts/c215bc69.0
+++ /dev/null
@@ -1,75 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
-EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ
-BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
-ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg
-bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ
-j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV
-Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG
-SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
-JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
-RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw
-MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5
-fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i
-+DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
-SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN
-QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+
-gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 913315222 (0x36701596)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E1
- Validity
- Not Before: Dec 10 18:10:23 1998 GMT
- Not After : Dec 10 18:40:23 2018 GMT
- Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E1
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
- Modulus:
- 00:a0:6c:81:a9:cf:34:1e:24:dd:fe:86:28:cc:de:
- 83:2f:f9:5e:d4:42:d2:e8:74:60:66:13:98:06:1c:
- a9:51:12:69:6f:31:55:b9:49:72:00:08:7e:d3:a5:
- 62:44:37:24:99:8f:d9:83:48:8f:99:6d:95:13:bb:
- 43:3b:2e:49:4e:88:37:c1:bb:58:7f:fe:e1:bd:f8:
- bb:61:cd:f3:47:c0:99:a6:f1:f3:91:e8:78:7c:00:
- cb:61:c9:44:27:71:69:55:4a:7e:49:4d:ed:a2:a3:
- be:02:4c:00:ca:02:a8:ee:01:02:31:64:0f:52:2d:
- 13:74:76:36:b5:7a:b4:2d:71
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
-
- Full Name:
- DirName: C = US, O = Digital Signature Trust Co., OU = DSTCA E1, CN = CRL1
-
- X509v3 Private Key Usage Period:
- Not Before: Dec 10 18:10:23 1998 GMT, Not After: Dec 10 18:10:23 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8
-
- X509v3 Subject Key Identifier:
- 6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 22:12:d8:7a:1d:dc:81:06:b6:09:65:b2:87:c8:1f:5e:b4:2f:
- e9:c4:1e:f2:3c:c1:bb:04:90:11:4a:83:4e:7e:93:b9:4d:42:
- c7:92:26:a0:5c:34:9a:38:72:f8:fd:6b:16:3e:20:ee:82:8b:
- 31:2a:93:36:85:23:88:8a:3c:03:68:d3:c9:09:0f:4d:fc:6c:
- a4:da:28:72:93:0e:89:80:b0:7d:fe:80:6f:65:6d:18:33:97:
- 8b:c2:6b:89:ee:60:3d:c8:9b:ef:7f:2b:32:62:73:93:cb:3c:
- e3:7b:e2:76:78:45:bc:a1:93:04:bb:86:9f:3a:5b:43:7a:c3:
- 8a:65
-SHA1 Fingerprint=81:96:8B:3A:EF:1C:DC:70:F5:FA:32:69:C2:92:A3:63:5B:D1:23:D3
diff --git a/luni/src/main/files/cacerts/c51c224c.0 b/luni/src/main/files/cacerts/c51c224c.0
new file mode 100644
index 0000000..6bf7f22
--- /dev/null
+++ b/luni/src/main/files/cacerts/c51c224c.0
@@ -0,0 +1,80 @@
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL
+ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx
+MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc
+MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+
+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH
+iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj
+vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA
+0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB
+OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/
+BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E
+FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01
+GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW
+zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4
+1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE
+f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F
+jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN
+ZetX2fNXlrtIzYE=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 1b:1f:ad:b6:20:f9:24:d3:36:6b:f7:c7:f1:8c:a0:59
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Trustis Limited, OU=Trustis FPS Root CA
+ Validity
+ Not Before: Dec 23 12:14:06 2003 GMT
+ Not After : Jan 21 11:36:54 2024 GMT
+ Subject: C=GB, O=Trustis Limited, OU=Trustis FPS Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c5:50:7b:9e:3b:35:d0:df:c4:8c:cd:8e:9b:ed:
+ a3:c0:36:99:f4:42:ea:a7:3e:80:83:0f:a6:a7:59:
+ 87:c9:90:45:43:7e:00:ea:86:79:2a:03:bd:3d:37:
+ 99:89:66:b7:e5:8a:56:86:93:9c:68:4b:68:04:8c:
+ 93:93:02:3e:30:d2:37:3a:22:61:89:1c:85:4e:7d:
+ 8f:d5:af:7b:35:f6:7e:28:47:89:31:dc:0e:79:64:
+ 1f:99:d2:5b:ba:fe:7f:60:bf:ad:eb:e7:3c:38:29:
+ 6a:2f:e5:91:0b:55:ff:ec:6f:58:d5:2d:c9:de:4c:
+ 66:71:8f:0c:d7:04:da:07:e6:1e:18:e3:bd:29:02:
+ a8:fa:1c:e1:5b:b9:83:a8:41:48:bc:1a:71:8d:e7:
+ 62:e5:2d:b2:eb:df:7c:cf:db:ab:5a:ca:31:f1:4c:
+ 22:f3:05:13:f7:82:f9:73:79:0c:be:d7:4b:1c:c0:
+ d1:15:3c:93:41:64:d1:e6:be:23:17:22:00:89:5e:
+ 1f:6b:a5:ac:6e:a7:4b:8c:ed:a3:72:e6:af:63:4d:
+ 2f:85:d2:14:35:9a:2e:4e:8c:ea:32:98:28:86:a1:
+ 91:09:41:3a:b4:e1:e3:f2:fa:f0:c9:0a:a2:41:dd:
+ a9:e3:03:c7:88:15:3b:1c:d4:1a:94:d7:9f:64:59:
+ 12:6d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:BA:FA:71:25:79:8B:57:41:25:21:86:0B:71:EB:B2:64:0E:8B:21:67
+
+ X509v3 Subject Key Identifier:
+ BA:FA:71:25:79:8B:57:41:25:21:86:0B:71:EB:B2:64:0E:8B:21:67
+ Signature Algorithm: sha1WithRSAEncryption
+ 7e:58:ff:fd:35:19:7d:9c:18:4f:9e:b0:2b:bc:8e:8c:14:ff:
+ 2c:a0:da:47:5b:c3:ef:81:2d:af:05:ea:74:48:5b:f3:3e:4e:
+ 07:c7:6d:c5:b3:93:cf:22:35:5c:b6:3f:75:27:5f:09:96:cd:
+ a0:fe:be:40:0c:5c:12:55:f8:93:82:ca:29:e9:5e:3f:56:57:
+ 8b:38:36:f7:45:1a:4c:28:cd:9e:41:b8:ed:56:4c:84:a4:40:
+ c8:b8:b0:a5:2b:69:70:04:6a:c3:f8:d4:12:32:f9:0e:c3:b1:
+ dc:32:84:44:2c:6f:cb:46:0f:ea:66:41:0f:4f:f1:58:a5:a6:
+ 0d:0d:0f:61:de:a5:9e:5d:7d:65:a1:3c:17:e7:a8:55:4e:ef:
+ a0:c7:ed:c6:44:7f:54:f5:a3:e0:8f:f0:7c:55:22:8f:29:b6:
+ 81:a3:e1:6d:4e:2c:1b:80:67:ec:ad:20:9f:0c:62:61:d5:97:
+ ff:43:ed:2d:c1:da:5d:29:2a:85:3f:ac:65:ee:86:0f:05:8d:
+ 90:5f:df:ee:9f:f4:bf:ee:1d:fb:98:e4:7f:90:2b:84:78:10:
+ 0e:6c:49:53:ef:15:5b:65:46:4a:5d:af:ba:fb:3a:72:1d:cd:
+ f6:25:88:1e:97:cc:21:9c:29:01:0d:65:eb:57:d9:f3:57:96:
+ bb:48:cd:81
+SHA1 Fingerprint=3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04
diff --git a/luni/src/main/files/cacerts/cb156124.0 b/luni/src/main/files/cacerts/cb156124.0
new file mode 100644
index 0000000..a5311ba
--- /dev/null
+++ b/luni/src/main/files/cacerts/cb156124.0
@@ -0,0 +1,127 @@
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV
+BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC
+aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV
+BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1
+Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz
+MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+
+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp
+em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
+ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY
+B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH
+D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF
+Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo
+q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D
+k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH
+fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut
+dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM
+ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8
+zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
+rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX
+U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6
+Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5
+XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF
+Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR
+HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY
+GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c
+77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3
++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK
+vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6
+FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl
+yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P
+AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD
+y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d
+NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7667447206703254355 (0x6a683e9c519bcb53)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=TR, L=Ankara, O=E-Tu\xC4\x9Fra EBG Bili\xC5\x9Fim Teknolojileri ve Hizmetleri A.\xC5\x9E., OU=E-Tugra Sertifikasyon Merkezi, CN=E-Tugra Certification Authority
+ Validity
+ Not Before: Mar 5 12:09:48 2013 GMT
+ Not After : Mar 3 12:09:48 2023 GMT
+ Subject: C=TR, L=Ankara, O=E-Tu\xC4\x9Fra EBG Bili\xC5\x9Fim Teknolojileri ve Hizmetleri A.\xC5\x9E., OU=E-Tugra Sertifikasyon Merkezi, CN=E-Tugra Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:e2:f5:3f:93:05:51:1e:85:62:54:5e:7a:0b:f5:
+ 18:07:83:ae:7e:af:7c:f7:d4:8a:6b:a5:63:43:39:
+ b9:4b:f7:c3:c6:64:89:3d:94:2e:54:80:52:39:39:
+ 07:4b:4b:dd:85:07:76:87:cc:bf:2f:95:4c:cc:7d:
+ a7:3d:bc:47:0f:98:70:f8:8c:85:1e:74:8e:92:6d:
+ 1b:40:d1:99:0d:bb:75:6e:c8:a9:6b:9a:c0:84:31:
+ af:ca:43:cb:eb:2b:34:e8:8f:97:6b:01:9b:d5:0e:
+ 4a:08:aa:5b:92:74:85:43:d3:80:ae:a1:88:5b:ae:
+ b3:ea:5e:cb:16:9a:77:44:c8:a1:f6:54:68:ce:de:
+ 8f:97:2b:ba:5b:40:02:0c:64:17:c0:b5:93:cd:e1:
+ f1:13:66:ce:0c:79:ef:d1:91:28:ab:5f:a0:12:52:
+ 30:73:19:8e:8f:e1:8c:07:a2:c3:bb:4a:f0:ea:1f:
+ 15:a8:ee:25:cc:a4:46:f8:1b:22:ef:b3:0e:43:ba:
+ 2c:24:b8:c5:2c:5c:d4:1c:f8:5d:64:bd:c3:93:5e:
+ 28:a7:3f:27:f1:8e:1e:d3:2a:50:05:a3:55:d9:cb:
+ e7:39:53:c0:98:9e:8c:54:62:8b:26:b0:f7:7d:8d:
+ 7c:e4:c6:9e:66:42:55:82:47:e7:b2:58:8d:66:f7:
+ 07:7c:2e:36:e6:50:1c:3f:db:43:24:c5:bf:86:47:
+ 79:b3:79:1c:f7:5a:f4:13:ec:6c:f8:3f:e2:59:1f:
+ 95:ee:42:3e:b9:ad:a8:32:85:49:97:46:fe:4b:31:
+ 8f:5a:cb:ad:74:47:1f:e9:91:b7:df:28:04:22:a0:
+ d4:0f:5d:e2:79:4f:ea:6c:85:86:bd:a8:a6:ce:e4:
+ fa:c3:e1:b3:ae:de:3c:51:ee:cb:13:7c:01:7f:84:
+ 0e:5d:51:94:9e:13:0c:b6:2e:a5:4c:f9:39:70:36:
+ 6f:96:ca:2e:0c:44:55:c5:ca:fa:5d:02:a3:df:d6:
+ 64:8c:5a:b3:01:0a:a9:b5:0a:47:17:ff:ef:91:40:
+ 2a:8e:a1:46:3a:31:98:e5:11:fc:cc:bb:49:56:8a:
+ fc:b9:d0:61:9a:6f:65:6c:e6:c3:cb:3e:75:49:fe:
+ 8f:a7:e2:89:c5:67:d7:9d:46:13:4e:31:76:3b:24:
+ b3:9e:11:65:86:ab:7f:ef:1d:d4:f8:bc:e7:ac:5a:
+ 5c:b7:5a:47:5c:55:ce:55:b4:22:71:5b:5b:0b:f0:
+ cf:dc:a0:61:64:ea:a9:d7:68:0a:63:a7:e0:0d:3f:
+ a0:af:d3:aa:d2:7e:ef:51:a0:e6:51:2b:55:92:15:
+ 17:53:cb:b7:66:0e:66:4c:f8:f9:75:4c:90:e7:12:
+ 70:c7:45
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 2E:E3:DB:B2:49:D0:9C:54:79:5C:FA:27:2A:FE:CC:4E:D2:E8:4E:54
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:2E:E3:DB:B2:49:D0:9C:54:79:5C:FA:27:2A:FE:CC:4E:D2:E8:4E:54
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 05:37:3a:f4:4d:b7:45:e2:45:75:24:8f:b6:77:52:e8:1c:d8:
+ 10:93:65:f3:f2:59:06:a4:3e:1e:29:ec:5d:d1:d0:ab:7c:e0:
+ 0a:90:48:78:ed:4e:98:03:99:fe:28:60:91:1d:30:1d:b8:63:
+ 7c:a8:e6:35:b5:fa:d3:61:76:e6:d6:07:4b:ca:69:9a:b2:84:
+ 7a:77:93:45:17:15:9f:24:d0:98:13:12:ff:bb:a0:2e:fd:4e:
+ 4c:87:f8:ce:5c:aa:98:1b:05:e0:00:46:4a:82:80:a5:33:8b:
+ 28:dc:ed:38:d3:df:e5:3e:e9:fe:fb:59:dd:61:84:4f:d2:54:
+ 96:13:61:13:3e:8f:80:69:be:93:47:b5:35:43:d2:5a:bb:3d:
+ 5c:ef:b3:42:47:cd:3b:55:13:06:b0:09:db:fd:63:f6:3a:88:
+ 0a:99:6f:7e:e1:ce:1b:53:6a:44:66:23:51:08:7b:bc:5b:52:
+ a2:fd:06:37:38:40:61:8f:4a:96:b8:90:37:f8:66:c7:78:90:
+ 00:15:2e:8b:ad:51:35:53:07:a8:6b:68:ae:f9:4e:3c:07:26:
+ cd:08:05:70:cc:39:3f:76:bd:a5:d3:67:26:01:86:a6:53:d2:
+ 60:3b:7c:43:7f:55:8a:bc:95:1a:c1:28:39:4c:1f:43:d2:91:
+ f4:72:59:8a:b9:56:fc:3f:b4:9d:da:70:9c:76:5a:8c:43:50:
+ ee:8e:30:72:4d:df:ff:49:f7:c6:a9:67:d9:6d:ac:02:11:e2:
+ 3a:16:25:a7:58:08:cb:6f:53:41:9c:48:38:47:68:33:d1:d7:
+ c7:8f:d4:74:21:d4:c3:05:90:7a:ff:ce:96:88:b1:15:29:5d:
+ 23:ab:d0:60:a1:12:4f:de:f4:17:cd:32:e5:c9:bf:c8:43:ad:
+ fd:2e:8e:f1:af:e2:f4:98:fa:12:1f:20:d8:c0:a7:0c:85:c5:
+ 90:f4:3b:2d:96:26:b1:2c:be:4c:ab:eb:b1:d2:8a:c9:db:78:
+ 13:0f:1e:09:9d:6d:8f:00:9f:02:da:c1:fa:1f:7a:7a:09:c4:
+ 4a:e6:88:2a:97:9f:89:8b:fd:37:5f:5f:3a:ce:38:59:86:4b:
+ af:71:0b:b4:d8:f2:70:4f:9f:32:13:e3:b0:a7:57:e5:da:da:
+ 43:cb:84:34:f2:28:c4:ea:6d:f4:2a:ef:c1:6b:76:da:fb:7e:
+ bb:85:3c:d2:53:c2:4d:be:71:e1:45:d1:fd:23:67:0d:13:75:
+ fb:cf:65:67:22:9d:ae:b0:09:d1:09:ff:1d:34:bf:fe:23:97:
+ 37:d2:39:fa:3d:0d:06:0b:b4:db:3b:a3:ab:6f:5c:1d:b6:7e:
+ e8:b3:82:34:ed:06:5c:24
+SHA1 Fingerprint=51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39
diff --git a/luni/src/main/files/cacerts/d66b55d9.0 b/luni/src/main/files/cacerts/d66b55d9.0
new file mode 100644
index 0000000..d34d5c2
--- /dev/null
+++ b/luni/src/main/files/cacerts/d66b55d9.0
@@ -0,0 +1,82 @@
+-----BEGIN CERTIFICATE-----
+MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc
+UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
+c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS
+S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg
+SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx
+OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry
+b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC
+VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE
+sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F
+ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY
+KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG
++7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG
+HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P
+IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M
+733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk
+Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G
+CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW
+AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
+aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5
+mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa
+XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ
+qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1, C=TR, L=Ankara, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. (c) Aral\xC4\xB1k 2007
+ Validity
+ Not Before: Dec 25 18:37:19 2007 GMT
+ Not After : Dec 22 18:37:19 2017 GMT
+ Subject: CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1, C=TR, L=Ankara, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. (c) Aral\xC4\xB1k 2007
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ab:b7:3e:0a:8c:c8:a5:58:15:e6:8a:ef:27:3d:
+ 4a:b4:e8:25:d3:cd:33:c2:20:dc:19:ee:88:3f:4d:
+ 62:f0:dd:13:77:8f:61:a9:2a:b5:d4:f2:b9:31:58:
+ 29:3b:2f:3f:6a:9c:6f:73:76:25:ee:34:20:80:ee:
+ ea:b7:f0:c4:0a:cd:2b:86:94:c9:e3:60:b1:44:52:
+ b2:5a:29:b4:91:97:83:d8:b7:a6:14:2f:29:49:a2:
+ f3:05:06:fb:b4:4f:da:a1:6c:9a:66:9f:f0:43:09:
+ ca:ea:72:8f:eb:00:d7:35:39:d7:56:17:47:17:30:
+ f4:be:bf:3f:c2:68:af:36:40:c1:a9:f4:a9:a7:e8:
+ 10:6b:08:8a:f7:86:1e:dc:9a:2a:15:06:f6:a3:f0:
+ f4:e0:c7:14:d4:51:7f:cf:b4:db:6d:af:47:96:17:
+ 9b:77:71:d8:a7:71:9d:24:0c:f6:94:3f:85:31:12:
+ 4f:ba:ee:4e:82:b8:b9:3e:8f:23:37:5e:cc:a2:aa:
+ 75:f7:18:6f:09:d3:ae:a7:54:28:34:fb:e1:e0:3b:
+ 60:7d:a0:be:79:89:86:c8:9f:2d:f9:0a:4b:c4:50:
+ a2:e7:fd:79:16:c7:7a:0b:18:cf:ce:4c:ef:7d:d6:
+ 07:6f:98:f1:af:b1:c1:7a:d7:81:35:b8:aa:17:b4:
+ e0:cb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 29:C5:90:AB:25:AF:11:E4:61:BF:A3:FF:88:61:91:E6:0E:FE:9C:81
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 10:0d:da:f8:3a:ec:28:d1:14:95:82:b1:12:2c:51:7a:41:25:
+ 36:4c:9f:ec:3f:1f:84:9d:65:54:5c:a8:16:02:40:fa:6e:1a:
+ 37:84:ef:72:9d:86:0a:55:9d:56:28:ac:66:2c:d0:3a:56:93:
+ 34:07:25:ad:08:b0:8f:c8:0f:09:59:ca:9d:98:1c:e5:54:f8:
+ b9:45:7f:6a:97:6f:88:68:4d:4a:06:26:37:88:02:0e:b6:c6:
+ d6:72:99:ce:6b:77:da:62:31:a4:56:1f:ae:5f:8d:77:da:5d:
+ f6:88:fc:1a:d9:9e:b5:81:f0:32:b8:e3:88:d0:9c:f3:6a:a0:
+ b9:9b:14:59:35:36:4f:cf:f3:8e:5e:5d:17:ad:15:95:d8:dd:
+ b2:d5:15:6e:00:4e:b3:4b:cf:66:94:e4:e0:cd:b5:05:da:63:
+ 57:8b:e5:b3:aa:db:c0:2e:1c:90:44:db:1a:5d:18:a4:ee:be:
+ 04:5b:99:d5:71:5f:55:65:64:62:d5:a2:9b:04:59:86:c8:62:
+ 77:e7:7c:82:45:6a:3d:17:bf:ec:9d:75:0c:ae:a3:6f:5a:d3:
+ 2f:98:36:f4:f0:f5:19:ab:11:5d:c8:a6:e3:2a:58:6a:42:09:
+ c3:bd:92:26:66:32:0d:5d:08:55:74:ff:8c:98:d0:0a:a6:84:
+ 6a:d1:39:7d
+SHA1 Fingerprint=F1:7F:6F:B6:31:DC:99:E3:A3:C8:7F:FE:1C:F1:81:10:88:D9:60:33
diff --git a/luni/src/main/files/cacerts/d777342d.0 b/luni/src/main/files/cacerts/d777342d.0
deleted file mode 100644
index f92094d..0000000
--- a/luni/src/main/files/cacerts/d777342d.0
+++ /dev/null
@@ -1,69 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDKTCCAhECCF9gWF8AAAAAMA0GCSqGSIb3DQEBBQUAMFcxCzAJBgNVBAYTAkpQ
-MSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRsw
-GQYDVQQDExJTZWN1cmVTaWduIFJvb3RDQTEwHhcNOTkwOTE1MTUwMDAxWhcNMjAw
-OTE1MTQ1OTU5WjBXMQswCQYDVQQGEwJKUDErMCkGA1UEChMiSmFwYW4gQ2VydGlm
-aWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEbMBkGA1UEAxMSU2VjdXJlU2lnbiBSb290
-Q0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6
-pLrn0syNr+hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJ
-FuHuBl5KB12rPdFQuJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpX
-izjwJh8x/M80jo93wT/jq1Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwL
-GZOhl5zjkWkfaOQvfRBtj2euwRCisF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP
-6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3Lg59v5iynDw0orM4mrXCoH/HwjHitP
-CCL+wQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBV7W97k+VFMU5o1VWBoggfbN0J
-xXgacFfI3wiBrmZ3xnUP5O9JiwNcbP8ckKRystMWErIG+EaGrr+nFduFTfrCLU2z
-tbBD73x+B9tfs1dGUXYHhkT9B+rxy0tFTWanMybE+UOqjRKz1I1otvcCebQtWtcD
-mAQsaZmv9GY7ZKyywCvIaVSeTE5IGI3OV7U7UeUb1/o5YNtWRRO+52bVI/Z8SACw
-TO80jSKssi7RTDjN+lgDBu46c4cKBTrK5K/Uwe4chX8lFs8nAR+EincI0NNG6CDs
-n6SM8bzNxBI2gB7HCSiv6Ai+wNOyPtcuZz2jzrs0+uKFzazOVR1FW3iF04V6
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 1 (0x0)
- Serial Number: 6872590196412514304 (0x5f60585f00000000)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1
- Validity
- Not Before: Sep 15 15:00:01 1999 GMT
- Not After : Sep 15 14:59:59 2020 GMT
- Subject: C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:94:90:0c:4b:71:29:1c:da:f6:68:79:7a:a4:ba:
- e7:d2:cc:8d:af:e8:47:90:99:1f:c6:2a:ea:97:63:
- e8:1f:ce:17:57:c6:1a:b3:a8:c7:7c:87:ed:35:35:
- 80:ba:ba:6e:6d:be:17:fe:cc:2d:1b:6c:ef:8a:00:
- 49:16:e1:ee:06:5e:4a:07:5d:ab:3d:d1:50:b8:91:
- 46:d4:d4:da:15:d8:94:5c:0e:ca:d7:da:bf:a0:f7:
- 49:3c:c8:bb:ce:ea:26:81:0a:14:2d:9c:0d:37:45:
- 6b:41:ca:57:8b:38:f0:26:1f:31:fc:cf:34:8e:8f:
- 77:c1:3f:e3:ab:54:3c:27:b4:ce:32:4c:55:13:62:
- fc:fe:3a:16:25:cf:1b:6b:a2:23:b7:e0:ea:02:69:
- bb:f7:22:71:6d:7c:0b:19:93:a1:97:9c:e3:91:69:
- 1f:68:e4:2f:7d:10:6d:8f:67:ae:c1:10:a2:b0:5e:
- 63:4a:97:f7:e6:78:a9:ad:26:bb:54:c9:df:b4:ee:
- c5:9e:d3:25:dd:13:68:53:f9:8f:e8:ec:e5:de:81:
- d6:78:3e:ee:50:40:b4:01:3c:ac:15:c1:82:3b:2e:
- 7f:f1:52:27:8b:72:e0:e7:db:f9:8b:29:c3:c3:4a:
- 2b:33:89:ab:5c:2a:07:fc:7c:23:1e:2b:4f:08:22:
- fe:c1
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 55:ed:6f:7b:93:e5:45:31:4e:68:d5:55:81:a2:08:1f:6c:dd:
- 09:c5:78:1a:70:57:c8:df:08:81:ae:66:77:c6:75:0f:e4:ef:
- 49:8b:03:5c:6c:ff:1c:90:a4:72:b2:d3:16:12:b2:06:f8:46:
- 86:ae:bf:a7:15:db:85:4d:fa:c2:2d:4d:b3:b5:b0:43:ef:7c:
- 7e:07:db:5f:b3:57:46:51:76:07:86:44:fd:07:ea:f1:cb:4b:
- 45:4d:66:a7:33:26:c4:f9:43:aa:8d:12:b3:d4:8d:68:b6:f7:
- 02:79:b4:2d:5a:d7:03:98:04:2c:69:99:af:f4:66:3b:64:ac:
- b2:c0:2b:c8:69:54:9e:4c:4e:48:18:8d:ce:57:b5:3b:51:e5:
- 1b:d7:fa:39:60:db:56:45:13:be:e7:66:d5:23:f6:7c:48:00:
- b0:4c:ef:34:8d:22:ac:b2:2e:d1:4c:38:cd:fa:58:03:06:ee:
- 3a:73:87:0a:05:3a:ca:e4:af:d4:c1:ee:1c:85:7f:25:16:cf:
- 27:01:1f:84:8a:77:08:d0:d3:46:e8:20:ec:9f:a4:8c:f1:bc:
- cd:c4:12:36:80:1e:c7:09:28:af:e8:08:be:c0:d3:b2:3e:d7:
- 2e:67:3d:a3:ce:bb:34:fa:e2:85:cd:ac:ce:55:1d:45:5b:78:
- 85:d3:85:7a
-SHA1 Fingerprint=CA:BB:51:67:24:00:58:8E:64:19:F1:D4:08:78:D0:40:3A:A2:02:64
diff --git a/luni/src/main/files/cacerts/d8274e24.0 b/luni/src/main/files/cacerts/d8274e24.0
deleted file mode 100644
index 55286e4..0000000
--- a/luni/src/main/files/cacerts/d8274e24.0
+++ /dev/null
@@ -1,89 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB
-ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt
-TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1
-NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0
-IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD
-VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS
-Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB
-DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2
-N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH
-iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe
-YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1
-axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g
-yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD
-AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh
-ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V
-VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB
-BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y
-IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs
-QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4
-ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM
-YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb
-QErNaLly7HF27FSOH4UMAWr6pjisH8SE
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number:
- 44:be:0c:8b:50:00:24:b4:11:d3:36:30:4b:c0:33:77
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications
- Validity
- Not Before: Jul 9 18:48:39 1999 GMT
- Not After : Jul 9 18:57:49 2019 GMT
- Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:b3:fb:91:a1:e4:36:55:85:ac:06:34:5b:a0:9a:
- 58:b2:f8:b5:0f:05:77:83:ae:32:b1:76:92:68:ec:
- 23:4a:c9:76:3f:e3:9c:b6:37:79:03:b9:ab:69:8d:
- 07:25:b6:19:67:e4:b0:1b:18:73:61:4a:e8:7e:cd:
- d3:2f:64:e3:a6:7c:0c:fa:17:80:a3:0d:47:89:4f:
- 51:71:2f:ee:fc:3f:f9:b8:16:80:87:89:93:25:20:
- 9a:43:82:69:24:76:28:59:35:a1:1d:c0:7f:83:06:
- 64:16:20:2c:d3:49:a4:85:b4:c0:61:7f:51:08:f8:
- 68:15:91:80:cb:a5:d5:ee:3b:3a:f4:84:04:5e:60:
- 59:a7:8c:34:72:ee:b8:78:c5:d1:3b:12:4a:6f:7e:
- 65:27:b9:a4:55:c5:b9:6f:43:a4:c5:1d:2c:99:c0:
- 52:a4:78:4c:15:b3:40:98:08:6b:43:c6:01:b0:7a:
- 7b:f5:6b:1c:22:3f:cb:ef:ff:a8:d0:3a:4b:76:15:
- 9e:d2:d1:c6:2e:e3:db:57:1b:32:a2:b8:6f:e8:86:
- a6:3f:70:ab:e5:70:92:ab:44:1e:40:50:fb:9c:a3:
- 62:e4:6c:6e:a0:c8:de:e2:80:42:fa:e9:2f:e8:ce:
- 32:04:8f:7c:8d:b7:1c:a3:35:3c:15:dd:9e:c3:ae:
- 97:a5
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage:
- Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
- X509v3 Basic Constraints: critical
- CA:TRUE
- X509v3 Subject Key Identifier:
- FA:86:C9:DB:E0:BA:E9:78:F5:4B:A8:D6:15:DF:F0:D3:E1:6A:14:3C
- X509v3 CRL Distribution Points:
-
- Full Name:
- URI:http://crl.usertrust.com/UTN-USERFirst-NetworkApplications.crl
-
- Signature Algorithm: sha1WithRSAEncryption
- a4:f3:25:cc:d1:d4:91:83:22:d0:cc:32:ab:9b:96:4e:34:91:
- 54:20:25:34:61:5f:2a:02:15:e1:8b:aa:ff:7d:64:51:cf:0a:
- ff:bc:7d:d8:21:6a:78:cb:2f:51:6f:f8:42:1d:33:bd:eb:b5:
- 7b:94:c3:c3:a9:a0:2d:df:d1:29:1f:1d:fe:8f:3f:bb:a8:45:
- 2a:7f:d1:6e:55:24:e2:bb:02:fb:31:3f:be:e8:bc:ec:40:2b:
- f8:01:d4:56:38:e4:ca:44:82:b5:61:20:21:67:65:f6:f0:0b:
- e7:34:f8:a5:c2:9c:a3:5c:40:1f:85:93:95:06:de:4f:d4:27:
- a9:b6:a5:fc:16:cd:73:31:3f:b8:65:27:cf:d4:53:1a:f0:ac:
- 6e:9f:4f:05:0c:03:81:a7:84:29:c4:5a:bd:64:57:72:ad:3b:
- cf:37:18:a6:98:c6:ad:06:b4:dc:08:a3:04:d5:29:a4:96:9a:
- 12:67:4a:8c:60:45:9d:f1:23:9a:b0:00:9c:68:b5:98:50:d3:
- ef:8e:2e:92:65:b1:48:3e:21:be:15:30:2a:0d:b5:0c:a3:6b:
- 3f:ae:7f:57:f5:1f:96:7c:df:6f:dd:82:30:2c:65:1b:40:4a:
- cd:68:b9:72:ec:71:76:ec:54:8e:1f:85:0c:01:6a:fa:a6:38:
- ac:1f:c4:84
-SHA1 Fingerprint=5D:98:9C:DB:15:96:11:36:51:65:64:1B:56:0F:DB:EA:2A:C2:3E:F1
diff --git a/luni/src/main/files/cacerts/e268a4c5.0 b/luni/src/main/files/cacerts/e268a4c5.0
new file mode 100644
index 0000000..c9f7dd8
--- /dev/null
+++ b/luni/src/main/files/cacerts/e268a4c5.0
@@ -0,0 +1,86 @@
+-----BEGIN CERTIFICATE-----
+MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
+b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw
+MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD
+VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul
+CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n
+tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl
+dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch
+PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC
++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O
+BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl
+MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk
+ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB
+IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X
+7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz
+43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
+eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl
+pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA
+WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Class 1 CA Root
+ Validity
+ Not Before: May 30 10:38:31 2000 GMT
+ Not After : May 30 10:38:31 2020 GMT
+ Subject: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Class 1 CA Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:96:96:d4:21:49:60:e2:6b:e8:41:07:0c:de:c4:
+ e0:dc:13:23:cd:c1:35:c7:fb:d6:4e:11:0a:67:5e:
+ f5:06:5b:6b:a5:08:3b:5b:29:16:3a:e7:87:b2:34:
+ 06:c5:bc:05:a5:03:7c:82:cb:29:10:ae:e1:88:81:
+ bd:d6:9e:d3:fe:2d:56:c1:15:ce:e3:26:9d:15:2e:
+ 10:fb:06:8f:30:04:de:a7:b4:63:b4:ff:b1:9c:ae:
+ 3c:af:77:b6:56:c5:b5:ab:a2:e9:69:3a:3d:0e:33:
+ 79:32:3f:70:82:92:99:61:6d:8d:30:08:8f:71:3f:
+ a6:48:57:19:f8:25:dc:4b:66:5c:a5:74:8f:98:ae:
+ c8:f9:c0:06:22:e7:ac:73:df:a5:2e:fb:52:dc:b1:
+ 15:65:20:fa:35:66:69:de:df:2c:f1:6e:bc:30:db:
+ 2c:24:12:db:eb:35:35:68:90:cb:00:b0:97:21:3d:
+ 74:21:23:65:34:2b:bb:78:59:a3:d6:e1:76:39:9a:
+ a4:49:8e:8c:74:af:6e:a4:9a:a3:d9:9b:d2:38:5c:
+ 9b:a2:18:cc:75:23:84:be:eb:e2:4d:33:71:8e:1a:
+ f0:c2:f8:c7:1d:a2:ad:03:97:2c:f8:cf:25:c6:f6:
+ b8:24:31:b1:63:5d:92:7f:63:f0:25:c9:53:2e:1f:
+ bf:4d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 95:B1:B4:F0:94:B6:BD:C7:DA:D1:11:09:21:BE:C1:AF:49:FD:10:7B
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:95:B1:B4:F0:94:B6:BD:C7:DA:D1:11:09:21:BE:C1:AF:49:FD:10:7B
+ DirName:/C=SE/O=AddTrust AB/OU=AddTrust TTP Network/CN=AddTrust Class 1 CA Root
+ serial:01
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 2c:6d:64:1b:1f:cd:0d:dd:b9:01:fa:96:63:34:32:48:47:99:
+ ae:97:ed:fd:72:16:a6:73:47:5a:f4:eb:dd:e9:f5:d6:fb:45:
+ cc:29:89:44:5d:bf:46:39:3d:e8:ee:bc:4d:54:86:1e:1d:6c:
+ e3:17:27:43:e1:89:56:2b:a9:6f:72:4e:49:33:e3:72:7c:2a:
+ 23:9a:bc:3e:ff:28:2a:ed:a3:ff:1c:23:ba:43:57:09:67:4d:
+ 4b:62:06:2d:f8:ff:6c:9d:60:1e:d8:1c:4b:7d:b5:31:2f:d9:
+ d0:7c:5d:f8:de:6b:83:18:78:37:57:2f:e8:33:07:67:df:1e:
+ c7:6b:2a:95:76:ae:8f:57:a3:f0:f4:52:b4:a9:53:08:cf:e0:
+ 4f:d3:7a:53:8b:fd:bb:1c:56:36:f2:fe:b2:b6:e5:76:bb:d5:
+ 22:65:a7:3f:fe:d1:66:ad:0b:bc:6b:99:86:ef:3f:7d:f3:18:
+ 32:ca:7b:c6:e3:ab:64:46:95:f8:26:69:d9:55:83:7b:2c:96:
+ 07:ff:59:2c:44:a3:c6:e5:e9:a9:dc:a1:63:80:5a:21:5e:21:
+ cf:53:54:f0:ba:6f:89:db:a8:aa:95:cf:8b:e3:71:cc:1e:1b:
+ 20:44:08:c0:7a:b6:40:fd:c4:e4:35:e1:1d:16:1c:d0:bc:2b:
+ 8e:d6:71:d9
+SHA1 Fingerprint=CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D
diff --git a/luni/src/main/files/cacerts/ed049835.0 b/luni/src/main/files/cacerts/ed049835.0
deleted file mode 100644
index 080502b..0000000
--- a/luni/src/main/files/cacerts/ed049835.0
+++ /dev/null
@@ -1,54 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM
-HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK
-qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj
-cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y
-cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP
-T8qAkbYp
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 32:88:8e:9a:d2:f5:eb:13:47:f8:7f:c4:20:37:25:f8
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Validity
- Not Before: May 18 00:00:00 1998 GMT
- Not After : Aug 1 23:59:59 2028 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
- Modulus:
- 00:ba:f0:e4:cf:f9:c4:ae:85:54:b9:07:57:f9:8f:
- c5:7f:68:11:f8:c4:17:b0:44:dc:e3:30:73:d5:2a:
- 62:2a:b8:d0:cc:1c:ed:28:5b:7e:bd:6a:dc:b3:91:
- 24:ca:41:62:3c:fc:02:01:bf:1c:16:31:94:05:97:
- 76:6e:a2:ad:bd:61:17:6c:4e:30:86:f0:51:37:2a:
- 50:c7:a8:62:81:dc:5b:4a:aa:c1:a0:b4:6e:eb:2f:
- e5:57:c5:b1:2b:40:70:db:5a:4d:a1:8e:1f:bd:03:
- 1f:d8:03:d4:8f:4c:99:71:bc:e2:82:cc:58:e8:98:
- 3a:86:d3:86:38:f3:00:29:1f
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 85:8c:12:c1:a7:b9:50:15:7a:cb:3e:ac:b8:43:8a:dc:aa:dd:
- 14:ba:89:81:7e:01:3c:23:71:21:88:2f:82:dc:63:fa:02:45:
- ac:45:59:d7:2a:58:44:5b:b7:9f:81:3b:92:68:3d:e2:37:24:
- f5:7b:6c:8f:76:35:96:09:a8:59:9d:b9:ce:23:ab:74:d6:83:
- fd:32:73:27:d8:69:3e:43:74:f6:ae:c5:89:9a:e7:53:7c:e9:
- 7b:f6:4b:f3:c1:65:83:de:8d:8a:9c:3c:88:8d:39:59:fc:aa:
- 3f:22:8d:a1:c1:66:50:81:72:4c:ed:22:64:4f:4f:ca:80:91:
- b6:29
-SHA1 Fingerprint=0B:77:BE:BB:CB:7A:A2:47:05:DE:CC:0F:BD:6A:02:FC:7A:BD:9B:52
diff --git a/luni/src/main/files/cacerts/ee90b008.0 b/luni/src/main/files/cacerts/ee90b008.0
new file mode 100644
index 0000000..f017edc
--- /dev/null
+++ b/luni/src/main/files/cacerts/ee90b008.0
@@ -0,0 +1,119 @@
+-----BEGIN CERTIFICATE-----
+MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1
+OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG
+A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ
+JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD
+vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo
+D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/
+Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW
+RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK
+HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN
+nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM
+0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i
+UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9
+Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg
+TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL
+BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
+2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX
+UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl
+6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK
+9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ
+HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI
+wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY
+XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l
+IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo
+hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr
+so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 59 (0x3b)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=IL, O=StartCom Ltd., CN=StartCom Certification Authority G2
+ Validity
+ Not Before: Jan 1 01:00:01 2010 GMT
+ Not After : Dec 31 23:59:01 2039 GMT
+ Subject: C=IL, O=StartCom Ltd., CN=StartCom Certification Authority G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:b6:89:36:5b:07:b7:20:36:bd:82:bb:e1:16:20:
+ 03:95:7a:af:0e:a3:55:c9:25:99:4a:c5:d0:56:41:
+ 87:90:4d:21:60:a4:14:87:3b:cd:fd:b2:3e:b4:67:
+ 03:6a:ed:e1:0f:4b:c0:91:85:70:45:e0:42:9e:de:
+ 29:23:d4:01:0d:a0:10:79:b8:db:03:bd:f3:a9:2f:
+ d1:c6:e0:0f:cb:9e:8a:14:0a:b8:bd:f6:56:62:f1:
+ c5:72:b6:32:25:d9:b2:f3:bd:65:c5:0d:2c:6e:d5:
+ 92:6f:18:8b:00:41:14:82:6f:40:20:26:7a:28:0f:
+ f5:1e:7f:27:f7:94:b1:37:3d:b7:c7:91:f7:e2:01:
+ ec:fd:94:89:e1:cc:6e:d3:36:d6:0a:19:79:ae:d7:
+ 34:82:65:ff:7c:42:bb:b6:dd:0b:a6:34:af:4b:60:
+ fe:7f:43:49:06:8b:8c:43:b8:56:f2:d9:7f:21:43:
+ 17:ea:a7:48:95:01:75:75:ea:2b:a5:43:95:ea:15:
+ 84:9d:08:8d:26:6e:55:9b:ab:dc:d2:39:d2:31:1d:
+ 60:e2:ac:cc:56:45:24:f5:1c:54:ab:ee:86:dd:96:
+ 32:85:f8:4c:4f:e8:95:76:b6:05:dd:36:23:67:bc:
+ ff:15:e2:ca:3b:e6:a6:ec:3b:ec:26:11:34:48:8d:
+ f6:80:2b:1a:23:02:eb:8a:1c:3a:76:2a:7b:56:16:
+ 1c:72:2a:b3:aa:e3:60:a5:00:9f:04:9b:e2:6f:1e:
+ 14:58:5b:a5:6c:8b:58:3c:c3:ba:4e:3a:5c:f7:e1:
+ 96:2b:3e:ef:07:bc:a4:e5:5d:cc:4d:9f:0d:e1:dc:
+ aa:bb:e1:6e:1a:ec:8f:e1:b6:4c:4d:79:72:5d:17:
+ 35:0b:1d:d7:c1:47:da:96:24:e0:d0:72:a8:5a:5f:
+ 66:2d:10:dc:2f:2a:13:ae:26:fe:0a:1c:19:cc:d0:
+ 3e:0b:9c:c8:09:2e:f9:5b:96:7a:47:9c:e9:7a:f3:
+ 05:50:74:95:73:9e:30:09:f3:97:82:5e:e6:8f:39:
+ 08:1e:59:e5:35:14:42:13:ff:00:9c:f7:be:aa:50:
+ cf:e2:51:48:d7:b8:6f:af:f8:4e:7e:33:98:92:14:
+ 62:3a:75:63:cf:7b:fa:de:82:3b:a9:bb:39:e2:c4:
+ bd:2c:00:0e:c8:17:ac:13:ef:4d:25:8e:d8:b3:90:
+ 2f:a9:da:29:7d:1d:af:74:3a:b2:27:c0:c1:1e:3e:
+ 75:a3:16:a9:af:7a:22:5d:9f:13:1a:cf:a7:a0:eb:
+ e3:86:0a:d3:fd:e6:96:95:d7:23:c8:37:dd:c4:7c:
+ aa:36:ac:98:1a:12:b1:e0:4e:e8:b1:3b:f5:d6:6f:
+ f1:30:d7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 4B:C5:B4:40:6B:AD:1C:B3:A5:1C:65:6E:46:36:89:87:05:0C:0E:B6
+ Signature Algorithm: sha256WithRSAEncryption
+ 73:57:3f:2c:d5:95:32:7e:37:db:96:92:eb:19:5e:7e:53:e7:
+ 41:ec:11:b6:47:ef:b5:de:ed:74:5c:c5:f1:8e:49:e0:fc:6e:
+ 99:13:cd:9f:8a:da:cd:3a:0a:d8:3a:5a:09:3f:5f:34:d0:2f:
+ 03:d2:66:1d:1a:bd:9c:90:37:c8:0c:8e:07:5a:94:45:46:2a:
+ e6:be:7a:da:a1:a9:a4:69:12:92:b0:7d:36:d4:44:87:d7:51:
+ f1:29:63:d6:75:cd:16:e4:27:89:1d:f8:c2:32:48:fd:db:99:
+ d0:8f:5f:54:74:cc:ac:67:34:11:62:d9:0c:0a:37:87:d1:a3:
+ 17:48:8e:d2:17:1d:f6:d7:fd:db:65:eb:fd:a8:d4:f5:d6:4f:
+ a4:5b:75:e8:c5:d2:60:b2:db:09:7e:25:8b:7b:ba:52:92:9e:
+ 3e:e8:c5:77:a1:3c:e0:4a:73:6b:61:cf:86:dc:43:ff:ff:21:
+ fe:23:5d:24:4a:f5:d3:6d:0f:62:04:05:57:82:da:6e:a4:33:
+ 25:79:4b:2e:54:19:8b:cc:2c:3d:30:e9:d1:06:ff:e8:32:46:
+ be:b5:33:76:77:a8:01:5d:96:c1:c1:d5:be:ae:25:c0:c9:1e:
+ 0a:09:20:88:a1:0e:c9:f3:6f:4d:82:54:00:20:a7:d2:8f:e4:
+ 39:54:17:2e:8d:1e:b8:1b:bb:1b:bd:9a:4e:3b:10:34:dc:9c:
+ 88:53:ef:a2:31:5b:58:4f:91:62:c8:c2:9a:9a:cd:15:5d:38:
+ a9:d6:be:f8:13:b5:9f:12:69:f2:50:62:ac:fb:17:37:f4:ee:
+ b8:75:67:60:10:fb:83:50:f9:44:b5:75:9c:40:17:b2:fe:fd:
+ 79:5d:6e:58:58:5f:30:fc:00:ae:af:33:c1:0e:4e:6c:ba:a7:
+ a6:a1:7f:32:db:38:e0:b1:72:17:0a:2b:91:ec:6a:63:26:ed:
+ 89:d4:78:cc:74:1e:05:f8:6b:fe:8c:6a:76:39:29:ae:65:23:
+ 12:95:08:22:1c:97:ce:5b:06:ee:0c:e2:bb:bc:1f:44:93:f6:
+ d8:38:45:05:21:ed:e4:ad:ab:12:b6:03:a4:42:2e:2d:c4:09:
+ 3a:03:67:69:84:9a:e1:59:90:8a:28:85:d5:5d:74:b1:d1:0e:
+ 20:58:9b:13:a5:b0:63:a6:ed:7b:47:fd:45:55:30:a4:ee:9a:
+ d4:e6:e2:87:ef:98:c9:32:82:11:29:22:bc:00:0a:31:5e:2d:
+ 0f:c0:8e:e9:6b:b2:8f:2e:06:d8:d1:91:c7:c6:12:f4:4c:fd:
+ 30:17:c3:c1:da:38:5b:e3:a9:ea:e6:a1:ba:79:ef:73:d8:b6:
+ 53:57:2d:f6:d0:e1:d7:48
+SHA1 Fingerprint=31:F1:FD:68:22:63:20:EE:C6:3B:3F:9D:EA:4A:3E:53:7C:7C:39:17
diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java
index c825118..68ca506 100644
--- a/luni/src/main/java/java/lang/System.java
+++ b/luni/src/main/java/java/lang/System.java
@@ -173,7 +173,7 @@
* local system, in nanoseconds. Equivalent to Linux's {@code CLOCK_MONOTONIC}.
*
* <p>This timestamp should only be used to measure a duration by comparing it
- * against another timestamp from the same process on the same device.
+ * against another timestamp on the same device.
* Values returned by this method do not have a defined correspondence to
* wall clock times; the zero value is typically whenever the device last booted.
* Use {@link #currentTimeMillis} if you want to know what time it is.
diff --git a/luni/src/main/java/java/lang/UnsafeByteSequence.java b/luni/src/main/java/java/lang/UnsafeByteSequence.java
deleted file mode 100644
index 228bb01..0000000
--- a/luni/src/main/java/java/lang/UnsafeByteSequence.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2010 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 java.lang;
-
-import java.nio.charset.Charset;
-
-/**
- * A cheaper ByteArrayOutputStream for internal use. This class is unsynchronized,
- * and returns its internal array if it's the right size. This makes String.getBytes("UTF-8")
- * 10x faster than the baseline non-fast-path implementation instead of 8x faster when using
- * ByteArrayOutputStream. When GC and uncontended synchronization become cheap, we should be
- * able to get rid of this class. In the meantime, if you need to add further API, please try
- * to keep it plug-compatible with ByteArrayOutputStream with an eye to future obsolescence.
- *
- * @hide
- */
-public class UnsafeByteSequence {
- private byte[] bytes;
- private int count;
-
- public UnsafeByteSequence(int initialCapacity) {
- this.bytes = new byte[initialCapacity];
- }
-
- public int size() {
- return count;
- }
-
- /**
- * Moves the write pointer back to the beginning of the sequence,
- * but without resizing or reallocating the buffer.
- */
- public void rewind() {
- count = 0;
- }
-
- public void write(byte[] buffer, int offset, int length) {
- if (count + length >= bytes.length) {
- byte[] newBytes = new byte[(count + length) * 2];
- System.arraycopy(bytes, 0, newBytes, 0, count);
- bytes = newBytes;
- }
- System.arraycopy(buffer, offset, bytes, count, length);
- count += length;
- }
-
- public void write(int b) {
- if (count == bytes.length) {
- byte[] newBytes = new byte[count * 2];
- System.arraycopy(bytes, 0, newBytes, 0, count);
- bytes = newBytes;
- }
- bytes[count++] = (byte) b;
- }
-
- @FindBugsSuppressWarnings("EI_EXPOSE_REP")
- public byte[] toByteArray() {
- if (count == bytes.length) {
- return bytes;
- }
- byte[] result = new byte[count];
- System.arraycopy(bytes, 0, result, 0, count);
- return result;
- }
-
- public String toString(Charset cs) {
- return new String(bytes, 0, count, cs);
- }
-}
diff --git a/luni/src/main/java/java/lang/reflect/Modifier.java b/luni/src/main/java/java/lang/reflect/Modifier.java
index fdbe3bb..5f973d5 100644
--- a/luni/src/main/java/java/lang/reflect/Modifier.java
+++ b/luni/src/main/java/java/lang/reflect/Modifier.java
@@ -109,6 +109,13 @@
public static final int MIRANDA = 0x8000;
/**
+ * Dex addition to mark instance constructors and static class
+ * initializer methods.
+ * @hide
+ */
+ public static final int CONSTRUCTOR = 0x10000;
+
+ /**
* Constructs a new {@code Modifier} instance.
*/
public Modifier() {
@@ -239,6 +246,14 @@
}
/**
+ * Returns true if the given modifiers contain {@link Modifier#CONSTRUCTOR}.
+ * @hide
+ */
+ public static boolean isConstructor(int modifiers) {
+ return ((modifiers & Modifier.CONSTRUCTOR) != 0);
+ }
+
+ /**
* Returns a string containing the string representation of all modifiers
* present in the specified modifiers. Modifiers appear in the order
* specified by the Java Language Specification.
diff --git a/luni/src/main/java/java/net/HttpURLConnection.java b/luni/src/main/java/java/net/HttpURLConnection.java
index d6b2435..89a4bc4 100644
--- a/luni/src/main/java/java/net/HttpURLConnection.java
+++ b/luni/src/main/java/java/net/HttpURLConnection.java
@@ -235,9 +235,9 @@
* until a connection is established.
*
* <h3>Response Caching</h3>
- * Android 4.0 (Ice Cream Sandwich) includes a response cache. See {@code
- * android.net.http.HttpResponseCache} for instructions on enabling HTTP caching
- * in your application.
+ * Android 4.0 (Ice Cream Sandwich, API level 15) includes a response cache. See
+ * {@code android.net.http.HttpResponseCache} for instructions on enabling HTTP
+ * caching in your application.
*
* <h3>Avoiding Bugs In Earlier Releases</h3>
* Prior to Android 2.2 (Froyo), this class had some frustrating bugs. In
diff --git a/luni/src/main/java/java/net/NetworkInterface.java b/luni/src/main/java/java/net/NetworkInterface.java
index b35424d..3128b98 100644
--- a/luni/src/main/java/java/net/NetworkInterface.java
+++ b/luni/src/main/java/java/net/NetworkInterface.java
@@ -17,10 +17,8 @@
package java.net;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,7 +26,6 @@
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.Libcore;
@@ -41,6 +38,8 @@
* system or to identify the local interface of a joined multicast group.
*/
public final class NetworkInterface extends Object {
+ private static final File SYS_CLASS_NET = new File("/sys/class/net");
+
private final String name;
private final int interfaceIndex;
private final List<InterfaceAddress> interfaceAddresses;
@@ -110,17 +109,42 @@
return null;
}
+ return getByNameInternal(interfaceName, readIfInet6Lines());
+ }
+
+ /**
+ * Similar to {@link #getByName(String)} except that {@code interfaceName}
+ * is assumed to be valid.
+ */
+ private static NetworkInterface getByNameInternal(String interfaceName,
+ String[] ifInet6Lines) throws SocketException {
int interfaceIndex = readIntFile("/sys/class/net/" + interfaceName + "/ifindex");
List<InetAddress> addresses = new ArrayList<InetAddress>();
List<InterfaceAddress> interfaceAddresses = new ArrayList<InterfaceAddress>();
- collectIpv6Addresses(interfaceName, interfaceIndex, addresses, interfaceAddresses);
+
+ collectIpv6Addresses(interfaceName, interfaceIndex, addresses, interfaceAddresses,
+ ifInet6Lines);
collectIpv4Address(interfaceName, addresses, interfaceAddresses);
return new NetworkInterface(interfaceName, interfaceIndex, addresses, interfaceAddresses);
}
- private static void collectIpv6Addresses(String interfaceName, int interfaceIndex,
- List<InetAddress> addresses, List<InterfaceAddress> interfaceAddresses) throws SocketException {
+ private static String[] readIfInet6Lines() throws SocketException {
+ try {
+ return IoUtils.readFileAsString("/proc/net/if_inet6").split("\n");
+ } catch (IOException ioe) {
+ throw rethrowAsSocketException(ioe);
+ }
+ }
+
+ /**
+ * Visible for testing only.
+ *
+ * @hide
+ */
+ public static void collectIpv6Addresses(String interfaceName, int interfaceIndex,
+ List<InetAddress> addresses, List<InterfaceAddress> interfaceAddresses,
+ String[] ifInet6Lines) throws SocketException {
// Format of /proc/net/if_inet6.
// All numeric fields are implicit hex,
// but not necessarily two-digit (http://code.google.com/p/android/issues/detail?id=34022).
@@ -132,12 +156,9 @@
// 6. interface name
// "00000000000000000000000000000001 01 80 10 80 lo"
// "fe800000000000000000000000000000 407 40 20 80 wlan0"
- BufferedReader in = null;
+ final String suffix = " " + interfaceName;
try {
- in = new BufferedReader(new FileReader("/proc/net/if_inet6"));
- String suffix = " " + interfaceName;
- String line;
- while ((line = in.readLine()) != null) {
+ for (String line : ifInet6Lines) {
if (!line.endsWith(suffix)) {
continue;
}
@@ -160,10 +181,8 @@
addresses.add(inet6Address);
interfaceAddresses.add(new InterfaceAddress(inet6Address, prefixLength));
}
- } catch (Exception ex) {
+ } catch (NumberFormatException ex) {
throw rethrowAsSocketException(ex);
- } finally {
- IoUtils.closeQuietly(in);
}
}
@@ -197,8 +216,14 @@
@FindBugsSuppressWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
private static boolean isValidInterfaceName(String interfaceName) {
+ final String[] interfaceList = SYS_CLASS_NET.list();
+ // We have no interfaces listed under /sys/class/net
+ if (interfaceList == null) {
+ return false;
+ }
+
// Don't just stat because a crafty user might have / or .. in the supposed interface name.
- for (String validName : new File("/sys/class/net").list()) {
+ for (String validName : interfaceList) {
if (interfaceName.equals(validName)) {
return true;
}
@@ -275,11 +300,13 @@
@FindBugsSuppressWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
private static List<NetworkInterface> getNetworkInterfacesList() throws SocketException {
- String[] interfaceNames = new File("/sys/class/net").list();
+ String[] interfaceNames = SYS_CLASS_NET.list();
NetworkInterface[] interfaces = new NetworkInterface[interfaceNames.length];
boolean[] done = new boolean[interfaces.length];
+
+ String[] ifInet6Lines = readIfInet6Lines();
for (int i = 0; i < interfaceNames.length; ++i) {
- interfaces[i] = NetworkInterface.getByName(interfaceNames[i]);
+ interfaces[i] = NetworkInterface.getByNameInternal(interfaceNames[i], ifInet6Lines);
// http://b/5833739: getByName can return null if the interface went away between our
// readdir(2) and our stat(2), so mark interfaces that disappeared as 'done'.
if (interfaces[i] == null) {
@@ -293,9 +320,9 @@
if (done[counter]) {
continue;
}
- int counter2 = counter;
+
// Checks whether the following interfaces are children.
- for (; counter2 < interfaces.length; counter2++) {
+ for (int counter2 = counter; counter2 < interfaces.length; counter2++) {
if (done[counter2]) {
continue;
}
@@ -304,7 +331,7 @@
interfaces[counter2].parent = interfaces[counter];
interfaces[counter].addresses.addAll(interfaces[counter2].addresses);
done[counter2] = true;
- }
+ }
}
result.add(interfaces[counter]);
done[counter] = true;
diff --git a/luni/src/main/java/java/nio/ByteBuffer.java b/luni/src/main/java/java/nio/ByteBuffer.java
index 324369a..456a309 100644
--- a/luni/src/main/java/java/nio/ByteBuffer.java
+++ b/luni/src/main/java/java/nio/ByteBuffer.java
@@ -156,10 +156,8 @@
* The new buffer is direct if this byte buffer is direct.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a char buffer which is based on the content of this byte buffer.
*/
public abstract CharBuffer asCharBuffer();
@@ -173,11 +171,8 @@
* The new buffer is direct if this byte buffer is direct.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a double buffer which is based on the content of this byte
- * buffer.
*/
public abstract DoubleBuffer asDoubleBuffer();
@@ -191,10 +186,8 @@
* The new buffer is direct if this byte buffer is direct.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a float buffer which is based on the content of this byte buffer.
*/
public abstract FloatBuffer asFloatBuffer();
@@ -208,10 +201,8 @@
* The new buffer is direct if this byte buffer is direct.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a int buffer which is based on the content of this byte buffer.
*/
public abstract IntBuffer asIntBuffer();
@@ -225,10 +216,8 @@
* The new buffer is direct if this byte buffer is direct.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a long buffer which is based on the content of this byte buffer.
*/
public abstract LongBuffer asLongBuffer();
@@ -257,10 +246,8 @@
* The new buffer is direct if this byte buffer is direct.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a short buffer which is based on the content of this byte buffer.
*/
public abstract ShortBuffer asShortBuffer();
@@ -313,14 +300,16 @@
* Returns a duplicated buffer that shares its content with this buffer.
* <p>
* The duplicated buffer's position, limit, capacity and mark are the same
- * as this buffer's. The duplicated buffer's read-only property and byte
- * order are the same as this buffer's too.
- * <p>
- * The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
- * position, limit and mark are independent.
+ * as this buffer's. The duplicated buffer's read-only property is the same
+ * as this buffer's.
*
- * @return a duplicated buffer that shares its content with this buffer.
+ * <p>Note that <i>in contrast to all non-{@code byte} buffers</i>,
+ * byte order is not preserved in the duplicate, and is instead set to
+ * big-endian.
+ *
+ * <p>The new buffer shares its content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffers'
+ * position, limit and mark are independent.
*/
public abstract ByteBuffer duplicate();
@@ -1020,10 +1009,8 @@
* read-only property and byte order are the same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a sliced buffer that shares its content with this buffer.
*/
public abstract ByteBuffer slice();
}
diff --git a/luni/src/main/java/java/nio/CharBuffer.java b/luni/src/main/java/java/nio/CharBuffer.java
index 57070a0..92cab01 100644
--- a/luni/src/main/java/java/nio/CharBuffer.java
+++ b/luni/src/main/java/java/nio/CharBuffer.java
@@ -236,10 +236,8 @@
* byte order are the same as this buffer's, too.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a duplicated buffer that shares its content with this buffer.
*/
public abstract CharBuffer duplicate();
@@ -597,10 +595,8 @@
* same as this buffer.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a sliced buffer that shares its content with this buffer.
*/
public abstract CharBuffer slice();
@@ -614,7 +610,7 @@
* buffer.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
*
* @param start
diff --git a/luni/src/main/java/java/nio/DoubleBuffer.java b/luni/src/main/java/java/nio/DoubleBuffer.java
index 401536d..2fa74d2 100644
--- a/luni/src/main/java/java/nio/DoubleBuffer.java
+++ b/luni/src/main/java/java/nio/DoubleBuffer.java
@@ -173,10 +173,8 @@
* order are the same as this buffer's, too.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a duplicated buffer that shares its content with this buffer.
*/
public abstract DoubleBuffer duplicate();
@@ -478,10 +476,8 @@
* the same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a sliced buffer that shares its content with this buffer.
*/
public abstract DoubleBuffer slice();
}
diff --git a/luni/src/main/java/java/nio/FloatBuffer.java b/luni/src/main/java/java/nio/FloatBuffer.java
index ac5e572..cb7e55e 100644
--- a/luni/src/main/java/java/nio/FloatBuffer.java
+++ b/luni/src/main/java/java/nio/FloatBuffer.java
@@ -174,10 +174,8 @@
* are same as this buffer too.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a duplicated buffer that shares its content with this buffer.
*/
public abstract FloatBuffer duplicate();
@@ -477,10 +475,8 @@
* same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a sliced buffer that shares its content with this buffer.
*/
public abstract FloatBuffer slice();
}
diff --git a/luni/src/main/java/java/nio/IntBuffer.java b/luni/src/main/java/java/nio/IntBuffer.java
index bbcc2e3..a20f6c2 100644
--- a/luni/src/main/java/java/nio/IntBuffer.java
+++ b/luni/src/main/java/java/nio/IntBuffer.java
@@ -168,10 +168,8 @@
* are the same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a duplicated buffer that shares its content with this buffer.
*/
public abstract IntBuffer duplicate();
@@ -466,10 +464,8 @@
* same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a sliced buffer that shares its content with this buffer.
*/
public abstract IntBuffer slice();
}
diff --git a/luni/src/main/java/java/nio/LongBuffer.java b/luni/src/main/java/java/nio/LongBuffer.java
index 58d7518..55adab6 100644
--- a/luni/src/main/java/java/nio/LongBuffer.java
+++ b/luni/src/main/java/java/nio/LongBuffer.java
@@ -170,10 +170,8 @@
* are same as this buffer's, too.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a duplicated buffer that shares its content with this buffer.
*/
public abstract LongBuffer duplicate();
@@ -467,10 +465,8 @@
* same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a sliced buffer that shares its content with this buffer.
*/
public abstract LongBuffer slice();
}
diff --git a/luni/src/main/java/java/nio/SelectorImpl.java b/luni/src/main/java/java/nio/SelectorImpl.java
index 41a2a52..d63fa63 100644
--- a/luni/src/main/java/java/nio/SelectorImpl.java
+++ b/luni/src/main/java/java/nio/SelectorImpl.java
@@ -84,7 +84,7 @@
super(selectorProvider);
/*
- * Create a pipes to trigger wakeup. We can't use a NIO pipe because it
+ * Create a pipe to trigger wakeup. We can't use a NIO pipe because it
* would be closed if the selecting thread is interrupted. Also
* configure the pipe so we can fully drain it without blocking.
*/
@@ -255,6 +255,11 @@
int ops = key.interestOpsNoCheck();
int selectedOps = 0;
+ if ((pollFd.revents & POLLHUP) != 0) {
+ // If there was an error condition, we definitely want to wake listeners,
+ // regardless of what they're waiting for. Failure is always interesting.
+ selectedOps |= ops;
+ }
if ((pollFd.revents & POLLIN) != 0) {
selectedOps |= ops & (OP_ACCEPT | OP_READ);
}
@@ -289,7 +294,7 @@
/**
* Removes cancelled keys from the key set and selected key set, and
- * deregisters the corresponding channels. Returns the number of keys
+ * unregisters the corresponding channels. Returns the number of keys
* removed from the selected key set.
*/
private int doCancel() {
diff --git a/luni/src/main/java/java/nio/ShortBuffer.java b/luni/src/main/java/java/nio/ShortBuffer.java
index ea20bed..8da01ed 100644
--- a/luni/src/main/java/java/nio/ShortBuffer.java
+++ b/luni/src/main/java/java/nio/ShortBuffer.java
@@ -170,10 +170,8 @@
* are the same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a duplicated buffer that shares its content with this buffer.
*/
public abstract ShortBuffer duplicate();
@@ -466,10 +464,8 @@
* same as this buffer's.
* <p>
* The new buffer shares its content with this buffer, which means either
- * buffer's change of content will be visible to the other. The two buffer's
+ * buffer's change of content will be visible to the other. The two buffers'
* position, limit and mark are independent.
- *
- * @return a sliced buffer that shares its content with this buffer.
*/
public abstract ShortBuffer slice();
}
diff --git a/luni/src/main/java/java/nio/charset/Charset.java b/luni/src/main/java/java/nio/charset/Charset.java
index 02cd42f..b3e8d0b 100644
--- a/luni/src/main/java/java/nio/charset/Charset.java
+++ b/luni/src/main/java/java/nio/charset/Charset.java
@@ -175,10 +175,11 @@
* <code>aliases</code>.
*/
protected Charset(String canonicalName, String[] aliases) {
- // check whether the given canonical name is legal
+ // Check whether the given canonical name is legal.
checkCharsetName(canonicalName);
this.canonicalName = canonicalName;
- // check each alias and put into a set
+
+ // Collect and check each unique alias.
this.aliasesSet = new HashSet<String>();
if (aliases != null) {
for (String alias : aliases) {
@@ -192,15 +193,21 @@
if (name.isEmpty()) {
throw new IllegalCharsetNameException(name);
}
- int length = name.length();
- for (int i = 0; i < length; ++i) {
- if (!isValidCharsetNameCharacter(name.charAt(i))) {
+ if (!isValidCharsetNameStart(name.charAt(0))) {
+ throw new IllegalCharsetNameException(name);
+ }
+ for (int i = 1; i < name.length(); ++i) {
+ if (!isValidCharsetNamePart(name.charAt(i))) {
throw new IllegalCharsetNameException(name);
}
}
}
- private static boolean isValidCharsetNameCharacter(char c) {
+ private static boolean isValidCharsetNameStart(char c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');
+ }
+
+ private static boolean isValidCharsetNamePart(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
c == '-' || c == '.' || c == ':' || c == '_';
}
@@ -210,7 +217,6 @@
* If multiple charsets have the same canonical name, it is unspecified which is returned in
* the map. This method may be slow. If you know which charset you're looking for, use
* {@link #forName}.
- * @return an immutable case-insensitive map from canonical names to {@code Charset} instances
*/
public static SortedMap<String, Charset> availableCharsets() {
// Start with a copy of the built-in charsets...
@@ -357,67 +363,56 @@
public abstract boolean contains(Charset charset);
/**
- * Gets a new instance of an encoder for this charset.
- *
- * @return a new instance of an encoder for this charset.
+ * Returns a new instance of an encoder for this charset.
*/
public abstract CharsetEncoder newEncoder();
/**
- * Gets a new instance of a decoder for this charset.
- *
- * @return a new instance of a decoder for this charset.
+ * Returns a new instance of a decoder for this charset.
*/
public abstract CharsetDecoder newDecoder();
/**
* Returns the canonical name of this charset.
+ *
+ * <p>If a charset is in the IANA registry, this will be the MIME-preferred name (a charset
+ * may have multiple IANA-registered names). Otherwise the canonical name will begin with "x-"
+ * or "X-".
*/
public final String name() {
return this.canonicalName;
}
/**
- * Gets the set of this charset's aliases.
- *
- * @return an unmodifiable set of this charset's aliases.
+ * Returns an unmodifiable set of this charset's aliases.
*/
public final Set<String> aliases() {
return Collections.unmodifiableSet(this.aliasesSet);
}
/**
- * Gets the name of this charset for the default locale.
+ * Returns the name of this charset for the default locale.
*
* <p>The default implementation returns the canonical name of this charset.
* Subclasses may return a localized display name.
- *
- * @return the name of this charset for the default locale.
*/
public String displayName() {
return this.canonicalName;
}
/**
- * Gets the name of this charset for the specified locale.
+ * Returns the name of this charset for the specified locale.
*
* <p>The default implementation returns the canonical name of this charset.
* Subclasses may return a localized display name.
- *
- * @param l
- * a certain locale
- * @return the name of this charset for the specified locale
*/
public String displayName(Locale l) {
return this.canonicalName;
}
/**
- * Indicates whether this charset is known to be registered in the IANA
+ * Returns true if this charset is known to be registered in the IANA
* Charset Registry.
- *
- * @return true if the charset is known to be registered, otherwise returns
- * false.
*/
public final boolean isRegistered() {
return !canonicalName.startsWith("x-") && !canonicalName.startsWith("X-");
@@ -425,8 +420,6 @@
/**
* Returns true if this charset supports encoding, false otherwise.
- *
- * @return true if this charset supports encoding, false otherwise.
*/
public boolean canEncode() {
return true;
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoder.java b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
index 7aa546c..7b53ceb 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
@@ -82,22 +82,22 @@
* @see java.nio.charset.CharsetEncoder
*/
public abstract class CharsetDecoder {
- private static final int INIT = 0;
- private static final int ONGOING = 1;
- private static final int END = 2;
- private static final int FLUSH = 3;
+ private static final String RESET = "RESET";
+ private static final String ONGOING = "ONGOING";
+ private static final String END_OF_INPUT = "END_OF_INPUT";
+ private static final String FLUSHED = "FLUSHED";
+
+ private final Charset charset;
private final float averageCharsPerByte;
private final float maxCharsPerByte;
- private final Charset cs;
+ private String replacementChars = "\ufffd";
- private CodingErrorAction malformedInputAction;
- private CodingErrorAction unmappableCharacterAction;
+ private String state = RESET;
- private String replacementChars;
-
- private int status;
+ private CodingErrorAction malformedInputAction = CodingErrorAction.REPORT;
+ private CodingErrorAction unmappableCharacterAction = CodingErrorAction.REPORT;
/**
* Constructs a new <code>CharsetDecoder</code> using the given
@@ -114,8 +114,7 @@
* the maximum number of characters created by this decoder for
* one input byte, must be positive.
* @throws IllegalArgumentException
- * if <code>averageCharsPerByte</code> or
- * <code>maxCharsPerByte</code> is negative.
+ * if {@code averageCharsPerByte <= 0 || maxCharsPerByte <= 0 || averageCharsPerByte > maxCharsPerByte}.
*/
protected CharsetDecoder(Charset charset, float averageCharsPerByte, float maxCharsPerByte) {
if (averageCharsPerByte <= 0 || maxCharsPerByte <= 0) {
@@ -126,11 +125,7 @@
}
this.averageCharsPerByte = averageCharsPerByte;
this.maxCharsPerByte = maxCharsPerByte;
- cs = charset;
- status = INIT;
- malformedInputAction = CodingErrorAction.REPORT;
- unmappableCharacterAction = CodingErrorAction.REPORT;
- replacementChars = "\ufffd";
+ this.charset = charset;
}
/**
@@ -145,7 +140,7 @@
* Returns the {@link Charset} which this decoder uses.
*/
public final Charset charset() {
- return cs;
+ return charset;
}
/**
@@ -182,35 +177,30 @@
* if another exception happened during the decode operation.
*/
public final CharBuffer decode(ByteBuffer in) throws CharacterCodingException {
- reset();
int length = (int) (in.remaining() * averageCharsPerByte);
- CharBuffer output = CharBuffer.allocate(length);
- CoderResult result = null;
- while (true) {
- result = decode(in, output, false);
- checkCoderResult(result);
- if (result.isUnderflow()) {
- break;
- } else if (result.isOverflow()) {
- output = allocateMore(output);
- }
- }
- result = decode(in, output, true);
- checkCoderResult(result);
+ CharBuffer out = CharBuffer.allocate(length);
- while (true) {
- result = flush(output);
- checkCoderResult(result);
- if (result.isOverflow()) {
- output = allocateMore(output);
+ reset();
+
+ while (state != FLUSHED) {
+ CoderResult result = decode(in, out, true);
+ if (result == CoderResult.OVERFLOW) {
+ out = allocateMore(out);
+ continue; // No point trying to flush to an already-full buffer.
} else {
- break;
+ checkCoderResult(result);
+ }
+
+ result = flush(out);
+ if (result == CoderResult.OVERFLOW) {
+ out = allocateMore(out);
+ } else {
+ checkCoderResult(result);
}
}
- output.flip();
- status = FLUSH;
- return output;
+ out.flip();
+ return out;
}
/*
@@ -304,54 +294,42 @@
* <code>BufferOverflowException</code>.
*/
public final CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput) {
- if (status == FLUSH || (!endOfInput && status == END)) {
- throw new IllegalStateException();
+ if (state != RESET && state != ONGOING && !(endOfInput && state == END_OF_INPUT)) {
+ throw illegalStateException();
}
- CoderResult result = null;
+ state = endOfInput ? END_OF_INPUT : ONGOING;
- // begin to decode
while (true) {
- CodingErrorAction action = null;
+ CoderResult result;
try {
result = decodeLoop(in, out);
} catch (BufferOverflowException ex) {
- // unexpected exception
throw new CoderMalfunctionError(ex);
} catch (BufferUnderflowException ex) {
- // unexpected exception
throw new CoderMalfunctionError(ex);
}
- /*
- * result handling
- */
- if (result.isUnderflow()) {
- int remaining = in.remaining();
- status = endOfInput ? END : ONGOING;
- if (endOfInput && remaining > 0) {
- result = CoderResult.malformedForLength(remaining);
+ if (result == CoderResult.UNDERFLOW) {
+ if (endOfInput && in.hasRemaining()) {
+ result = CoderResult.malformedForLength(in.remaining());
} else {
return result;
}
- }
- if (result.isOverflow()) {
+ } else if (result == CoderResult.OVERFLOW) {
return result;
}
- // set coding error handle action
- action = malformedInputAction;
- if (result.isUnmappable()) {
- action = unmappableCharacterAction;
- }
- // If the action is IGNORE or REPLACE, we should continue decoding.
- if (action == CodingErrorAction.REPLACE) {
+
+ // We have a real error, so do what the appropriate action tells us what to do...
+ CodingErrorAction action =
+ result.isUnmappable() ? unmappableCharacterAction : malformedInputAction;
+ if (action == CodingErrorAction.REPORT) {
+ return result;
+ } else if (action == CodingErrorAction.REPLACE) {
if (out.remaining() < replacementChars.length()) {
return CoderResult.OVERFLOW;
}
out.put(replacementChars);
- } else {
- if (action != CodingErrorAction.IGNORE)
- return result;
}
in.position(in.position() + result.length());
}
@@ -442,20 +420,15 @@
* @return <code>CoderResult.UNDERFLOW</code> or
* <code>CoderResult.OVERFLOW</code>.
* @throws IllegalStateException
- * if this decoder hasn't read all input bytes during one
- * decoding process, which means neither after calling
- * {@link #decode(ByteBuffer) decode(ByteBuffer)} nor after
- * calling {@link #decode(ByteBuffer, CharBuffer, boolean)
- * decode(ByteBuffer, CharBuffer, boolean)} with true as value
- * for the last boolean parameter.
+ * if this decoder isn't already flushed or at end of input.
*/
public final CoderResult flush(CharBuffer out) {
- if (status != END && status != INIT) {
- throw new IllegalStateException();
+ if (state != FLUSHED && state != END_OF_INPUT) {
+ throw illegalStateException();
}
CoderResult result = implFlush(out);
if (result == CoderResult.UNDERFLOW) {
- status = FLUSH;
+ state = FLUSHED;
}
return result;
}
@@ -582,7 +555,7 @@
* the new action on malformed input error.
* @return this decoder.
* @throws IllegalArgumentException
- * if {@code newAction} is {@code null}.
+ * if {@code newAction == null}.
*/
public final CharsetDecoder onMalformedInput(CodingErrorAction newAction) {
if (newAction == null) {
@@ -604,7 +577,7 @@
* the new action on unmappable character error.
* @return this decoder.
* @throws IllegalArgumentException
- * if {@code newAction} is {@code null}.
+ * if {@code newAction == null}.
*/
public final CharsetDecoder onUnmappableCharacter(CodingErrorAction newAction) {
if (newAction == null) {
@@ -631,8 +604,8 @@
* new replacement as argument.
*
* @param replacement
- * the replacement string, cannot be null or empty. Its length
- * cannot be larger than {@link #maxCharsPerByte()}.
+ * the replacement string cannot be null, empty, or longer
+ * than {@link #maxCharsPerByte()}.
* @return this decoder.
* @throws IllegalArgumentException
* if the given replacement cannot satisfy the requirement
@@ -655,14 +628,12 @@
}
/**
- * Resets this decoder. This method will reset the internal status, and then
- * calls <code>implReset()</code> to reset any status related to the
+ * Resets this decoder. This method will reset the internal state, and then
+ * calls {@link #implReset} to reset any state related to the
* specific charset.
- *
- * @return this decoder.
*/
public final CharsetDecoder reset() {
- status = INIT;
+ state = RESET;
implReset();
return this;
}
@@ -674,4 +645,8 @@
public CodingErrorAction unmappableCharacterAction() {
return unmappableCharacterAction;
}
+
+ private IllegalStateException illegalStateException() {
+ throw new IllegalStateException("State: " + state);
+ }
}
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoder.java b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
index c2d74a1..9217bba 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
@@ -76,25 +76,22 @@
* @see java.nio.charset.CharsetDecoder
*/
public abstract class CharsetEncoder {
- private static final int READY = 0;
- private static final int ONGOING = 1;
- private static final int END = 2;
- private static final int FLUSH = 3;
- private static final int INIT = 4;
+ private static final String RESET = "RESET";
+ private static final String ONGOING = "ONGOING";
+ private static final String END_OF_INPUT = "END_OF_INPUT";
+ private static final String FLUSHED = "FLUSHED";
- private final Charset cs;
+ private final Charset charset;
private final float averageBytesPerChar;
private final float maxBytesPerChar;
private byte[] replacementBytes;
- private int status;
- // internal status indicates encode(CharBuffer) operation is finished
- private boolean finished;
+ private String state = RESET;
- private CodingErrorAction malformedInputAction;
- private CodingErrorAction unmappableCharacterAction;
+ private CodingErrorAction malformedInputAction = CodingErrorAction.REPORT;
+ private CodingErrorAction unmappableCharacterAction = CodingErrorAction.REPORT;
// decoder instance for this encoder's charset, used for replacement value checking
private CharsetDecoder decoder;
@@ -139,12 +136,9 @@
if (averageBytesPerChar > maxBytesPerChar) {
throw new IllegalArgumentException("averageBytesPerChar is greater than maxBytesPerChar");
}
- this.cs = cs;
+ this.charset = cs;
this.averageBytesPerChar = averageBytesPerChar;
this.maxBytesPerChar = maxBytesPerChar;
- status = INIT;
- malformedInputAction = CodingErrorAction.REPORT;
- unmappableCharacterAction = CodingErrorAction.REPORT;
if (trusted) {
// The RI enforces unnecessary restrictions on the replacement bytes. We trust ICU to
// know what it's doing. Doing so lets us support ICU's EUC-JP, SCSU, and Shift_JIS.
@@ -165,7 +159,7 @@
/**
* Tests whether the given character can be encoded by this encoder.
*
- * <p>Note that this method may change the internal status of this encoder, so
+ * <p>Note that this method may change the internal state of this encoder, so
* it should not be called when another encoding process is ongoing,
* otherwise it will throw an <code>IllegalStateException</code>.
*
@@ -179,7 +173,7 @@
* Tests whether the given <code>CharSequence</code> can be encoded by this
* encoder.
*
- * <p>Note that this method may change the internal status of this encoder, so
+ * <p>Note that this method may change the internal state of this encoder, so
* it should not be called when another encode process is ongoing, otherwise
* it will throw an <code>IllegalStateException</code>.
*
@@ -193,18 +187,19 @@
cb = CharBuffer.wrap(sequence);
}
- if (status == FLUSH || status == INIT) {
- status = READY;
+ if (state == FLUSHED) {
+ reset();
}
- if (status != READY) {
- throw new IllegalStateException();
+ if (state != RESET) {
+ throw illegalStateException();
}
+
CodingErrorAction originalMalformedInputAction = malformedInputAction;
CodingErrorAction originalUnmappableCharacterAction = unmappableCharacterAction;
onMalformedInput(CodingErrorAction.REPORT);
onUnmappableCharacter(CodingErrorAction.REPORT);
try {
- this.encode(cb);
+ encode(cb);
return true;
} catch (CharacterCodingException e) {
return false;
@@ -219,7 +214,7 @@
* Returns the {@link Charset} which this encoder uses.
*/
public final Charset charset() {
- return cs;
+ return charset;
}
/**
@@ -256,43 +251,30 @@
public final ByteBuffer encode(CharBuffer in) throws CharacterCodingException {
int length = (int) (in.remaining() * averageBytesPerChar);
ByteBuffer out = ByteBuffer.allocate(length);
- if (in.hasRemaining() == false) {
- return out;
- }
reset();
- while (in.hasRemaining()) {
+ while (state != FLUSHED) {
CoderResult result = encode(in, out, true);
- if (result == CoderResult.UNDERFLOW) {
- break;
- } else if (result == CoderResult.OVERFLOW) {
+ if (result == CoderResult.OVERFLOW) {
out = allocateMore(out);
- continue;
+ continue; // No point trying to flush to an already-full buffer.
} else {
checkCoderResult(result);
}
result = flush(out);
- if (result == CoderResult.UNDERFLOW) {
- break;
- } else if (result == CoderResult.OVERFLOW) {
+ if (result == CoderResult.OVERFLOW) {
out = allocateMore(out);
- continue;
} else {
checkCoderResult(result);
}
}
out.flip();
- status = READY;
- finished = true;
return out;
}
- /*
- * checks the result whether it needs to throw CharacterCodingException.
- */
private void checkCoderResult(CoderResult result) throws CharacterCodingException {
if (malformedInputAction == CodingErrorAction.REPORT && result.isMalformed()) {
throw new MalformedInputException(result.length());
@@ -301,7 +283,6 @@
}
}
- // allocate more spaces to the given ByteBuffer
private ByteBuffer allocateMore(ByteBuffer output) {
if (output.capacity() == 0) {
return ByteBuffer.allocate(1);
@@ -375,26 +356,22 @@
* <code>BufferUnderflowException</code>.
*/
public final CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput) {
- // If the previous step is encode(CharBuffer), then no more input is needed
- // thus endOfInput should not be false
- if (status == READY && finished && !endOfInput) {
- throw new IllegalStateException();
- }
- if (status == FLUSH || (!endOfInput && status == END)) {
- throw new IllegalStateException();
+ if (state != RESET && state != ONGOING && !(endOfInput && state == END_OF_INPUT)) {
+ throw illegalStateException();
}
- status = endOfInput ? END : ONGOING;
+ state = endOfInput ? END_OF_INPUT : ONGOING;
while (true) {
CoderResult result;
try {
result = encodeLoop(in, out);
- } catch (BufferOverflowException e) {
- throw new CoderMalfunctionError(e);
- } catch (BufferUnderflowException e) {
- throw new CoderMalfunctionError(e);
+ } catch (BufferOverflowException ex) {
+ throw new CoderMalfunctionError(ex);
+ } catch (BufferUnderflowException ex) {
+ throw new CoderMalfunctionError(ex);
}
+
if (result == CoderResult.UNDERFLOW) {
if (endOfInput && in.hasRemaining()) {
result = CoderResult.malformedForLength(in.remaining());
@@ -404,12 +381,13 @@
} else if (result == CoderResult.OVERFLOW) {
return result;
}
+
+ // We have a real error, so do what the appropriate action tells us what to do...
CodingErrorAction action =
result.isUnmappable() ? unmappableCharacterAction : malformedInputAction;
if (action == CodingErrorAction.REPORT) {
return result;
- }
- if (action == CodingErrorAction.REPLACE) {
+ } else if (action == CodingErrorAction.REPLACE) {
if (out.remaining() < replacementBytes.length) {
return CoderResult.OVERFLOW;
}
@@ -477,20 +455,15 @@
* @return <code>CoderResult.UNDERFLOW</code> or
* <code>CoderResult.OVERFLOW</code>.
* @throws IllegalStateException
- * if this encoder hasn't read all input characters during one
- * encoding process, which means neither after calling
- * {@link #encode(CharBuffer) encode(CharBuffer)} nor after
- * calling {@link #encode(CharBuffer, ByteBuffer, boolean)
- * encode(CharBuffer, ByteBuffer, boolean)} with {@code true}
- * for the last boolean parameter.
+ * if this encoder isn't already flushed or at end of input.
*/
public final CoderResult flush(ByteBuffer out) {
- if (status != END && status != READY) {
- throw new IllegalStateException();
+ if (state != FLUSHED && state != END_OF_INPUT) {
+ throw illegalStateException();
}
CoderResult result = implFlush(out);
if (result == CoderResult.UNDERFLOW) {
- status = FLUSH;
+ state = FLUSHED;
}
return result;
}
@@ -559,7 +532,7 @@
*/
public boolean isLegalReplacement(byte[] replacement) {
if (decoder == null) {
- decoder = cs.newDecoder();
+ decoder = charset.newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
}
@@ -675,14 +648,12 @@
}
/**
- * Resets this encoder. This method will reset the internal status and then
- * calls <code>implReset()</code> to reset any status related to the
+ * Resets this encoder. This method will reset the internal state and then
+ * calls {@link #implReset} to reset any state related to the
* specific charset.
- *
- * @return this encoder.
*/
public final CharsetEncoder reset() {
- status = INIT;
+ state = RESET;
implReset();
return this;
}
@@ -694,4 +665,8 @@
public CodingErrorAction unmappableCharacterAction() {
return unmappableCharacterAction;
}
+
+ private IllegalStateException illegalStateException() {
+ throw new IllegalStateException("State: " + state);
+ }
}
diff --git a/luni/src/main/java/java/text/SimpleDateFormat.java b/luni/src/main/java/java/text/SimpleDateFormat.java
index 04287ae..5fd8a56 100644
--- a/luni/src/main/java/java/text/SimpleDateFormat.java
+++ b/luni/src/main/java/java/text/SimpleDateFormat.java
@@ -94,7 +94,7 @@
* <p>Fractional seconds are handled specially: they're zero-padded on the <i>right</i>.
*
* <p>The two pattern characters {@code L} and {@code c} are ICU-compatible extensions, not
- * available in the RI or in Android before Android 2.3 "Gingerbread" (API level 9). These
+ * available in the RI or in Android before Android 2.3 (Gingerbread, API level 9). These
* extensions are necessary for correct localization in languages such as Russian
* that make a grammatical distinction between, say, the word "June" in the sentence "June" and
* in the sentence "June 10th"; the former is the stand-alone form, the latter the regular
@@ -102,7 +102,7 @@
* and {@code c} is equivalent, but for weekday names.
*
* <p>Five-count patterns (such as "MMMMM") used for the shortest non-numeric
- * representation of a field were introduced in Jelly Bean MR2 (API level 18).
+ * representation of a field were introduced in Android 4.3 (Jelly Bean MR2, API level 18).
*
* <p>When two numeric fields are directly adjacent with no intervening delimiter
* characters, they constitute a run of adjacent numeric fields. Such runs are
@@ -1130,22 +1130,35 @@
return position.getIndex();
}
- private int parseText(String string, int offset, String[] text, int field) {
- int found = -1;
- for (int i = 0; i < text.length; i++) {
- if (text[i].isEmpty()) {
+ private int parseText(String string, int offset, String[] options, int field) {
+ // We search for the longest match, in case some entries are substrings of others.
+ int bestIndex = -1;
+ int bestLength = -1;
+ for (int i = 0; i < options.length; ++i) {
+ String option = options[i];
+ int optionLength = option.length();
+ if (optionLength == 0) {
continue;
}
- if (string.regionMatches(true, offset, text[i], 0, text[i].length())) {
- // Search for the longest match, in case some fields are subsets
- if (found == -1 || text[i].length() > text[found].length()) {
- found = i;
+ if (string.regionMatches(true, offset, option, 0, optionLength)) {
+ if (bestIndex == -1 || optionLength > bestLength) {
+ bestIndex = i;
+ bestLength = optionLength;
+ }
+ } else if (option.charAt(optionLength - 1) == '.') {
+ // If CLDR has abbreviated forms like "Aug.", we should accept "Aug" too.
+ // https://code.google.com/p/android/issues/detail?id=59383
+ if (string.regionMatches(true, offset, option, 0, optionLength - 1)) {
+ if (bestIndex == -1 || optionLength - 1 > bestLength) {
+ bestIndex = i;
+ bestLength = optionLength - 1;
+ }
}
}
}
- if (found != -1) {
- calendar.set(field, found);
- return offset + text[found].length();
+ if (bestIndex != -1) {
+ calendar.set(field, bestIndex);
+ return offset + bestLength;
}
return -offset - 1;
}
diff --git a/luni/src/main/java/java/util/Arrays.java b/luni/src/main/java/java/util/Arrays.java
index 2c84795..d3e05a0 100644
--- a/luni/src/main/java/java/util/Arrays.java
+++ b/luni/src/main/java/java/util/Arrays.java
@@ -1963,32 +1963,22 @@
/**
* Sorts the specified array in ascending natural order.
*
- * @param array
- * the {@code Object} array to be sorted.
- * @throws ClassCastException
- * if an element in the array does not implement {@code Comparable}
- * or if some elements cannot be compared to each other.
- * @see #sort(Object[], int, int)
+ * @throws ClassCastException if any element does not implement {@code Comparable},
+ * or if {@code compareTo} throws for any pair of elements.
*/
public static void sort(Object[] array) {
ComparableTimSort.sort(array);
}
/**
- * Sorts the specified range in the array in ascending natural order. All
- * elements must implement the {@code Comparable} interface and must be
- * comparable to each other without a {@code ClassCastException} being
- * thrown.
+ * Sorts the specified range in the array in ascending natural order.
*
- * @param array
- * the {@code Object} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
- * @throws ClassCastException
- * if an element in the array does not implement {@code Comparable}
- * or some elements cannot be compared to each other.
+ * @throws ClassCastException if any element does not implement {@code Comparable},
+ * or if {@code compareTo} throws for any pair of elements.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
@@ -2003,8 +1993,6 @@
* All elements must be comparable to each other without a
* {@code ClassCastException} being thrown.
*
- * @param array
- * the {@code Object} array to be sorted.
* @param start
* the start index to sort.
* @param end
@@ -2013,7 +2001,7 @@
* the {@code Comparator}.
* @throws ClassCastException
* if elements in the array cannot be compared to each other
- * using the {@code Comparator}.
+ * using the given {@code Comparator}.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
@@ -2027,10 +2015,6 @@
* Sorts the specified array using the specified {@code Comparator}. All elements
* must be comparable to each other without a {@code ClassCastException} being thrown.
*
- * @param array
- * the {@code Object} array to be sorted.
- * @param comparator
- * the {@code Comparator}.
* @throws ClassCastException
* if elements in the array cannot be compared to each other
* using the {@code Comparator}.
diff --git a/luni/src/main/java/java/util/Collections.java b/luni/src/main/java/java/util/Collections.java
index 932dcc1..ce4e579 100644
--- a/luni/src/main/java/java/util/Collections.java
+++ b/luni/src/main/java/java/util/Collections.java
@@ -1852,14 +1852,11 @@
}
/**
- * Sorts the specified list in ascending natural order. The algorithm is
+ * Sorts the given list in ascending natural order. The algorithm is
* stable which means equal elements don't get reordered.
*
- * @param list
- * the list to be sorted.
- * @throws ClassCastException
- * when an element in the List does not implement Comparable or
- * elements cannot be compared to each other.
+ * @throws ClassCastException if any element does not implement {@code Comparable},
+ * or if {@code compareTo} throws for any pair of elements.
*/
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
@@ -1874,16 +1871,11 @@
}
/**
- * Sorts the specified list using the specified comparator. The algorithm is
+ * Sorts the given list using the given comparator. The algorithm is
* stable which means equal elements don't get reordered.
*
- * @param list
- * the list to be sorted.
- * @param comparator
- * the comparator.
- * @throws ClassCastException
- * when elements in the list cannot be compared to each other
- * using the comparator.
+ * @throws ClassCastException if any element does not implement {@code Comparable},
+ * or if {@code compareTo} throws for any pair of elements.
*/
@SuppressWarnings("unchecked")
public static <T> void sort(List<T> list, Comparator<? super T> comparator) {
diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java
index 23db9dc..fc8f7c6 100644
--- a/luni/src/main/java/java/util/Locale.java
+++ b/luni/src/main/java/java/util/Locale.java
@@ -66,12 +66,34 @@
* <p>Here are the versions of ICU (and the corresponding CLDR and Unicode versions) used in
* various Android releases:
* <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
- * <tr><td>Cupcake/Donut/Eclair</td> <td>ICU 3.8</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-5">CLDR 1.5</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.0.0/">Unicode 5.0</a></td></tr>
- * <tr><td>Froyo</td> <td>ICU 4.2</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-7">CLDR 1.7</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.1.0/">Unicode 5.1</a></td></tr>
- * <tr><td>Gingerbread/Honeycomb</td><td>ICU 4.4</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-8">CLDR 1.8</a></td> <td><a href="http://www.unicode.org/versions/Unicode5.2.0/">Unicode 5.2</a></td></tr>
- * <tr><td>Ice Cream Sandwich</td> <td>ICU 4.6</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-9">CLDR 1.9</a></td> <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr>
- * <tr><td>Jelly Bean</td> <td>ICU 4.8</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-2-0">CLDR 2.0</a></td> <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr>
- * <tr><td>Jelly Bean MR2</td> <td>ICU 50</td> <td><a href="http://cldr.unicode.org/index/downloads/cldr-21-1">CLDR 22.1</a></td> <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr>
+ * <tr><td>Android 1.5 (Cupcake)/Android 1.6 (Donut)/Android 2.0 (Eclair)</td>
+ * <td>ICU 3.8</td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-5">CLDR 1.5</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode5.0.0/">Unicode 5.0</a></td></tr>
+ * <tr><td>Android 2.2 (Froyo)</td>
+ * <td>ICU 4.2</td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-7">CLDR 1.7</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode5.1.0/">Unicode 5.1</a></td></tr>
+ * <tr><td>Android 2.3 (Gingerbread)/Android 3.0 (Honeycomb)</td>
+ * <td>ICU 4.4</td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-8">CLDR 1.8</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode5.2.0/">Unicode 5.2</a></td></tr>
+ * <tr><td>Android 4.0 (Ice Cream Sandwich)</td>
+ * <td>ICU 4.6</td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-1-9">CLDR 1.9</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr>
+ * <tr><td>Android 4.1 (Jelly Bean)</td>
+ * <td>ICU 4.8</td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-2-0">CLDR 2.0</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode 6.0</a></td></tr>
+ * <tr><td>Android 4.3 (Jelly Bean MR2)</td>
+ * <td>ICU 50</td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-22-1">CLDR 22.1</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr>
+ * <tr><td>Android 4.4 (KitKat)</td>
+ * <td>ICU 51</td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-23">CLDR 23</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr>
* </table>
*
* <a name="default_locale"><h3>Be wary of the default locale</h3></a>
diff --git a/luni/src/main/java/java/util/PriorityQueue.java b/luni/src/main/java/java/util/PriorityQueue.java
index cc9bfe6..690c1f8 100644
--- a/luni/src/main/java/java/util/PriorityQueue.java
+++ b/luni/src/main/java/java/util/PriorityQueue.java
@@ -26,8 +26,8 @@
* construction time. If the queue uses natural ordering, only elements that are
* comparable are permitted to be inserted into the queue.
* <p>
- * The least element of the specified ordering is stored at the head of the
- * queue and the greatest element is stored at the tail of the queue.
+ * The least element of the specified ordering is the first retrieved with
+ * {@link #poll()} and the greatest element is the last.
* <p>
* A PriorityQueue is not synchronized. If multiple threads will have to access
* it concurrently, use the {@link java.util.concurrent.PriorityBlockingQueue}.
@@ -341,9 +341,13 @@
private void removeAt(int index) {
size--;
- elements[index] = elements[size];
+ E moved = elements[size];
+ elements[index] = moved;
siftDown(index);
elements[size] = null;
+ if (moved == elements[index]) {
+ siftUp(index);
+ }
}
private int compare(E o1, E o2) {
diff --git a/luni/src/main/java/java/util/Scanner.java b/luni/src/main/java/java/util/Scanner.java
index 972e6f9..7d504b7 100644
--- a/luni/src/main/java/java/util/Scanner.java
+++ b/luni/src/main/java/java/util/Scanner.java
@@ -76,7 +76,7 @@
private static final Pattern MULTI_LINE_TERMINATOR = Pattern.compile("(" + NL + ")+");
// Pattern used to recognize a line with a line terminator.
- private static final Pattern LINE_PATTERN = Pattern.compile(".*(" + NL + ")|.+(" + NL + ")?");
+ private static final Pattern LINE_PATTERN = Pattern.compile(".*(" + NL + ")|.+$");
// The pattern matches anything.
private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*");
@@ -86,7 +86,7 @@
// The input source of scanner.
private Readable input;
- private CharBuffer buffer;
+ private CharBuffer buffer = CharBuffer.allocate(1024);
private Pattern delimiter = DEFAULT_DELIMITER;
@@ -125,17 +125,6 @@
private int cachedIntegerPatternRadix = -1;
private Pattern cachedIntegerPattern = null;
- private enum DataType {
- /*
- * Stands for Integer
- */
- INT,
- /*
- * Stands for Float
- */
- FLOAT;
- }
-
/**
* Creates a {@code Scanner} with the specified {@code File} as input. The default charset
* is applied when reading the file.
@@ -171,12 +160,11 @@
throw new IllegalArgumentException("charsetName == null");
}
try {
- input = new InputStreamReader(fis, charsetName);
+ setInput(new InputStreamReader(fis, charsetName));
} catch (UnsupportedEncodingException e) {
IoUtils.closeQuietly(fis);
throw new IllegalArgumentException(e.getMessage());
}
- initialization();
}
/**
@@ -186,8 +174,7 @@
* the string to be scanned.
*/
public Scanner(String src) {
- input = new StringReader(src);
- initialization();
+ setInput(new StringReader(src));
}
/**
@@ -217,11 +204,10 @@
throw new NullPointerException("src == null");
}
try {
- input = new InputStreamReader(src, charsetName);
+ setInput(new InputStreamReader(src, charsetName));
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e.getMessage());
}
- initialization();
}
/**
@@ -234,8 +220,7 @@
if (src == null) {
throw new NullPointerException("src == null");
}
- input = src;
- initialization();
+ setInput(src);
}
/**
@@ -267,8 +252,13 @@
if (charsetName == null) {
throw new IllegalArgumentException("charsetName == null");
}
- input = Channels.newReader(src, charsetName);
- initialization();
+ setInput(Channels.newReader(src, charsetName));
+ }
+
+ private void setInput(Readable input) {
+ this.input = input;
+ buffer.limit(0);
+ matcher = delimiter.matcher(buffer);
}
/**
@@ -454,20 +444,12 @@
matcher.usePattern(pattern);
String result = null;
- int findEndIndex = 0;
- int horizonEndIndex = 0;
- if (horizon == 0) {
- horizonEndIndex = Integer.MAX_VALUE;
- } else {
- horizonEndIndex = findStartIndex + horizon;
- }
+ int horizonEndIndex = (horizon == 0) ? Integer.MAX_VALUE : findStartIndex + horizon;
while (true) {
- findEndIndex = bufferLength;
-
// If horizon > 0, then search up to
// min( bufferLength, findStartIndex + horizon).
// Otherwise search until readable is exhausted.
- findEndIndex = Math.min(horizonEndIndex, bufferLength);
+ int findEndIndex = Math.min(horizonEndIndex, bufferLength);
// If horizon == 0, consider horizon as always outside buffer.
boolean isHorizonInBuffer = (horizonEndIndex <= bufferLength);
// First, try to find pattern within buffer. If pattern can not be
@@ -475,7 +457,7 @@
// util horizonEndIndex is exceeded or no more input left.
matcher.region(findStartIndex, findEndIndex);
if (matcher.find()) {
- if (isHorizonInBuffer || inputExhausted) {
+ if ((horizon == 0 && !matcher.hitEnd()) || isHorizonInBuffer || inputExhausted) {
result = matcher.group();
break;
}
@@ -644,7 +626,7 @@
boolean isBigIntegerValue = false;
if (hasNext(integerPattern)) {
String intString = matcher.group();
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
try {
cachedNextValue = new BigInteger(intString, radix);
isBigIntegerValue = true;
@@ -698,7 +680,7 @@
boolean isByteValue = false;
if (hasNext(integerPattern)) {
String intString = matcher.group();
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
try {
cachedNextValue = Byte.valueOf(intString, radix);
isByteValue = true;
@@ -790,7 +772,7 @@
boolean isIntValue = false;
if (hasNext(integerPattern)) {
String intString = matcher.group();
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
try {
cachedNextValue = Integer.valueOf(intString, radix);
isIntValue = true;
@@ -802,39 +784,16 @@
}
/**
- * Returns whether there is a line terminator in the input.
+ * Returns true if there is a line terminator in the input.
* This method may block.
*
- * @return {@code true} if there is a line terminator in the input,
- * otherwise, {@code false}.
- * @throws IllegalStateException
- * if the {@code Scanner} is closed.
+ * @throws IllegalStateException if this {@code Scanner} is closed.
*/
public boolean hasNextLine() {
- checkOpen();
- matcher.usePattern(LINE_PATTERN);
- matcher.region(findStartIndex, bufferLength);
-
- boolean hasNextLine = false;
- while (true) {
- if (matcher.find()) {
- if (inputExhausted || matcher.end() != bufferLength) {
- matchSuccessful = true;
- hasNextLine = true;
- break;
- }
- } else {
- if (inputExhausted) {
- matchSuccessful = false;
- break;
- }
- }
- if (!inputExhausted) {
- readMore();
- resetMatcher();
- }
- }
- return hasNextLine;
+ saveCurrentStatus();
+ String result = findWithinHorizon(LINE_PATTERN, 0);
+ recoverPreviousStatus();
+ return result != null;
}
/**
@@ -867,7 +826,7 @@
boolean isLongValue = false;
if (hasNext(integerPattern)) {
String intString = matcher.group();
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
try {
cachedNextValue = Long.valueOf(intString, radix);
isLongValue = true;
@@ -908,7 +867,7 @@
boolean isShortValue = false;
if (hasNext(integerPattern)) {
String intString = matcher.group();
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
try {
cachedNextValue = Short.valueOf(intString, radix);
isShortValue = true;
@@ -1122,7 +1081,7 @@
}
Pattern integerPattern = getIntegerPattern(radix);
String intString = next(integerPattern);
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
BigInteger bigIntegerValue;
try {
bigIntegerValue = new BigInteger(intString, radix);
@@ -1200,7 +1159,7 @@
}
Pattern integerPattern = getIntegerPattern(radix);
String intString = next(integerPattern);
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
byte byteValue = 0;
try {
byteValue = Byte.parseByte(intString, radix);
@@ -1350,7 +1309,7 @@
}
Pattern integerPattern = getIntegerPattern(radix);
String intString = next(integerPattern);
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
int intValue = 0;
try {
intValue = Integer.parseInt(intString, radix);
@@ -1380,6 +1339,7 @@
matcher.usePattern(LINE_PATTERN);
matcher.region(findStartIndex, bufferLength);
+
String result = null;
while (true) {
if (matcher.find()) {
@@ -1461,7 +1421,7 @@
}
Pattern integerPattern = getIntegerPattern(radix);
String intString = next(integerPattern);
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
long longValue = 0;
try {
longValue = Long.parseLong(intString, radix);
@@ -1523,7 +1483,7 @@
}
Pattern integerPattern = getIntegerPattern(radix);
String intString = next(integerPattern);
- intString = removeLocaleInfo(intString, DataType.INT);
+ intString = removeLocaleInfo(intString, int.class);
short shortValue = 0;
try {
shortValue = Short.parseShort(intString, radix);
@@ -1689,15 +1649,6 @@
throw new UnsupportedOperationException();
}
- /*
- * Initialize some components.
- */
- private void initialization() {
- buffer = CharBuffer.allocate(1024);
- buffer.limit(0);
- matcher = delimiter.matcher(buffer);
- }
-
private void checkOpen() {
if (closed) {
throw new IllegalStateException();
@@ -1719,6 +1670,8 @@
} else {
matcher.reset(buffer);
}
+ matcher.useTransparentBounds(true);
+ matcher.useAnchoringBounds(false);
matcher.region(findStartIndex, bufferLength);
}
@@ -1852,17 +1805,17 @@
if ((exponentIndex = floatString.indexOf('e')) != -1 || (exponentIndex = floatString.indexOf('E')) != -1) {
String decimalNumeralString = floatString.substring(0, exponentIndex);
String exponentString = floatString.substring(exponentIndex + 1, floatString.length());
- decimalNumeralString = removeLocaleInfo(decimalNumeralString, DataType.FLOAT);
+ decimalNumeralString = removeLocaleInfo(decimalNumeralString, float.class);
return decimalNumeralString + "e" + exponentString;
}
- return removeLocaleInfo(floatString, DataType.FLOAT);
+ return removeLocaleInfo(floatString, float.class);
}
/*
* Remove the locale specific prefixes, group separators, and locale
* specific suffixes from input string
*/
- private String removeLocaleInfo(String token, DataType type) {
+ private String removeLocaleInfo(String token, Class<?> type) {
DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols();
StringBuilder tokenBuilder = new StringBuilder(token);
@@ -1877,14 +1830,13 @@
String decimalSeparator = String.valueOf(dfs.getDecimalSeparator());
separatorIndex = tokenBuilder.indexOf(decimalSeparator);
StringBuilder result = new StringBuilder("");
- if (DataType.INT == type) {
+ if (type == int.class) {
for (int i = 0; i < tokenBuilder.length(); i++) {
if (Character.digit(tokenBuilder.charAt(i), Character.MAX_RADIX) != -1) {
result.append(tokenBuilder.charAt(i));
}
}
- }
- if (DataType.FLOAT == type) {
+ } else if (type == float.class) {
if (tokenBuilder.toString().equals(dfs.getNaN())) {
result.append("NaN");
} else if (tokenBuilder.toString().equals(dfs.getInfinity())) {
@@ -1896,6 +1848,8 @@
}
}
}
+ } else {
+ throw new AssertionError("Unsupported type: " + type);
}
// Token is NaN or Infinity
if (result.length() == 0) {
@@ -1968,7 +1922,7 @@
}
tokenEndIndex = findDelimiterAfter();
// If the second delimiter is not found
- if (-1 == tokenEndIndex) {
+ if (tokenEndIndex == -1) {
// Just first Delimiter Exists
if (findStartIndex == bufferLength) {
return false;
@@ -2022,7 +1976,7 @@
int tokenEndIndex;
boolean setSuccess = false;
// If no delimiter exists, but something exists in this scanner
- if (-1 == findIndex && preStartIndex != bufferLength) {
+ if (findIndex == -1 && preStartIndex != bufferLength) {
tokenStartIndex = preStartIndex;
tokenEndIndex = bufferLength;
findStartIndex = bufferLength;
@@ -2088,20 +2042,16 @@
} catch (IOException e) {
// Consider the scenario: readable puts 4 chars into
// buffer and then an IOException is thrown out. In this case,
- // buffer is
- // actually grown, but readable.read() will never return.
+ // buffer is actually grown, but readable.read() will never return.
bufferLength = buffer.position();
- /*
- * Uses -1 to record IOException occurring, and no more input can be
- * read.
- */
+ // Use -1 to record IOException occurring, and no more input can be read.
readCount = -1;
lastIOException = e;
}
buffer.flip();
buffer.position(oldPosition);
- if (-1 == readCount) {
+ if (readCount == -1) {
inputExhausted = true;
} else {
bufferLength = readCount + bufferLength;
diff --git a/luni/src/main/java/java/util/jar/ManifestReader.java b/luni/src/main/java/java/util/jar/ManifestReader.java
index 2faaa90..8760884 100644
--- a/luni/src/main/java/java/util/jar/ManifestReader.java
+++ b/luni/src/main/java/java/util/jar/ManifestReader.java
@@ -17,6 +17,7 @@
package java.util.jar;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
@@ -31,7 +32,7 @@
// but a manifest might have thousands of entries.
private final HashMap<String, Attributes.Name> attributeNameCache = new HashMap<String, Attributes.Name>();
- private final UnsafeByteSequence valueBuffer = new UnsafeByteSequence(80);
+ private final ByteArrayOutputStream valueBuffer = new ByteArrayOutputStream(80);
private final byte[] buf;
@@ -141,7 +142,7 @@
boolean lastCr = false;
int mark = pos;
int last = pos;
- valueBuffer.rewind();
+ valueBuffer.reset();
while (pos < buf.length) {
byte next = buf[pos++];
switch (next) {
@@ -175,6 +176,8 @@
}
valueBuffer.write(buf, mark, last - mark);
- value = valueBuffer.toString(StandardCharsets.UTF_8);
+ // A bit frustrating that that Charset.forName will be called
+ // again.
+ value = valueBuffer.toString(StandardCharsets.UTF_8.name());
}
}
diff --git a/luni/src/main/java/java/util/regex/Matcher.java b/luni/src/main/java/java/util/regex/Matcher.java
index d58d092..02531d7 100644
--- a/luni/src/main/java/java/util/regex/Matcher.java
+++ b/luni/src/main/java/java/util/regex/Matcher.java
@@ -557,12 +557,10 @@
}
/**
- * Indicates whether this matcher has anchoring bounds enabled. When
+ * Returns true if this matcher has anchoring bounds enabled. When
* anchoring bounds are enabled, the start and end of the input match the
* '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
* by default.
- *
- * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
*/
public boolean hasAnchoringBounds() {
return anchoringBounds;
@@ -600,12 +598,10 @@
}
/**
- * Indicates whether this matcher has transparent bounds enabled. When
+ * Returns true if this matcher has transparent bounds enabled. When
* transparent bounds are enabled, the parts of the input outside the region
* are subject to lookahead and lookbehind, otherwise they are not.
* Transparent bounds are disabled by default.
- *
- * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
*/
public boolean hasTransparentBounds() {
return transparentBounds;
@@ -628,8 +624,10 @@
}
/**
- * Returns true if and only if more input might change a successful match into an
- * unsuccessful one.
+ * Returns true if the most recent match succeeded and additional input could cause
+ * it to fail. If this method returns false and a match was found, then more input
+ * might change the match but the match won't be lost. If a match was not found,
+ * then requireEnd has no meaning.
*/
public boolean requireEnd() {
synchronized (this) {
@@ -638,7 +636,9 @@
}
/**
- * Returns true if and only if the last match hit the end of the input.
+ * Returns true if the most recent matching operation attempted to access
+ * additional text beyond the available input, meaning that additional input
+ * could change the results of the match.
*/
public boolean hitEnd() {
synchronized (this) {
diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java
index e91c73e..f64c717 100644
--- a/luni/src/main/java/java/util/zip/ZipEntry.java
+++ b/luni/src/main/java/java/util/zip/ZipEntry.java
@@ -343,19 +343,21 @@
/*
* Internal constructor. Creates a new ZipEntry by reading the
- * Central Directory Entry from "in", which must be positioned at
- * the CDE signature.
+ * Central Directory Entry (CDE) from "in", which must be positioned
+ * at the CDE signature.
*
- * On exit, "in" will be positioned at the start of the next entry.
+ * On exit, "in" will be positioned at the start of the next entry
+ * in the Central Directory.
*/
- ZipEntry(byte[] hdrBuf, InputStream in) throws IOException {
- Streams.readFully(in, hdrBuf, 0, hdrBuf.length);
+ ZipEntry(byte[] cdeHdrBuf, InputStream cdStream) throws IOException {
+ Streams.readFully(cdStream, cdeHdrBuf, 0, cdeHdrBuf.length);
- BufferIterator it = HeapBufferIterator.iterator(hdrBuf, 0, hdrBuf.length, ByteOrder.LITTLE_ENDIAN);
+ BufferIterator it = HeapBufferIterator.iterator(cdeHdrBuf, 0, cdeHdrBuf.length,
+ ByteOrder.LITTLE_ENDIAN);
int sig = it.readInt();
if (sig != CENSIG) {
- throw new ZipException("Central Directory Entry not found");
+ ZipFile.throwZipException("Central Directory Entry", sig);
}
it.seek(8);
@@ -383,24 +385,24 @@
localHeaderRelOffset = ((long) it.readInt()) & 0xffffffffL;
byte[] nameBytes = new byte[nameLength];
- Streams.readFully(in, nameBytes, 0, nameBytes.length);
+ Streams.readFully(cdStream, nameBytes, 0, nameBytes.length);
if (containsNulByte(nameBytes)) {
throw new ZipException("Filename contains NUL byte: " + Arrays.toString(nameBytes));
}
name = new String(nameBytes, 0, nameBytes.length, StandardCharsets.UTF_8);
+ if (extraLength > 0) {
+ extra = new byte[extraLength];
+ Streams.readFully(cdStream, extra, 0, extraLength);
+ }
+
// The RI has always assumed UTF-8. (If GPBF_UTF8_FLAG isn't set, the encoding is
// actually IBM-437.)
if (commentByteCount > 0) {
byte[] commentBytes = new byte[commentByteCount];
- Streams.readFully(in, commentBytes, 0, commentByteCount);
+ Streams.readFully(cdStream, commentBytes, 0, commentByteCount);
comment = new String(commentBytes, 0, commentBytes.length, StandardCharsets.UTF_8);
}
-
- if (extraLength > 0) {
- extra = new byte[extraLength];
- Streams.readFully(in, extra, 0, extraLength);
- }
}
private static boolean containsNulByte(byte[] bytes) {
diff --git a/luni/src/main/java/java/util/zip/ZipFile.java b/luni/src/main/java/java/util/zip/ZipFile.java
index 47bc48e..c25bbc1 100644
--- a/luni/src/main/java/java/util/zip/ZipFile.java
+++ b/luni/src/main/java/java/util/zip/ZipFile.java
@@ -20,7 +20,6 @@
import dalvik.system.CloseGuard;
import java.io.BufferedInputStream;
import java.io.Closeable;
-import java.io.EOFException;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
@@ -40,7 +39,7 @@
* the zip file's central directory up front (from the constructor), but if you're using
* {@link #getEntry} to look up multiple files by name, you get the benefit of this index.
*
- * <p>If you only want to iterate through all the files (using {@link #entries}, you should
+ * <p>If you only want to iterate through all the files (using {@link #entries()}, you should
* consider {@link ZipInputStream}, which provides stream-like read access to a zip file and
* has a lower up-front cost because you don't pay to build an in-memory index.
*
@@ -274,11 +273,19 @@
RandomAccessFile localRaf = raf;
synchronized (localRaf) {
// We don't know the entry data's start position. All we have is the
- // position of the entry's local header. At position 6 we find the
- // General Purpose Bit Flag.
+ // position of the entry's local header.
// http://www.pkware.com/documents/casestudies/APPNOTE.TXT
- RAFStream rafStream= new RAFStream(localRaf, entry.localHeaderRelOffset + 6);
+ RAFStream rafStream = new RAFStream(localRaf, entry.localHeaderRelOffset);
DataInputStream is = new DataInputStream(rafStream);
+
+ final int localMagic = Integer.reverseBytes(is.readInt());
+ if (localMagic != LOCSIG) {
+ throwZipException("Local File Header", localMagic);
+ }
+
+ is.skipBytes(2);
+
+ // At position 6 we find the General Purpose Bit Flag.
int gpbf = Short.reverseBytes(is.readShort()) & 0xffff;
if ((gpbf & ZipFile.GPBF_UNSUPPORTED_MASK) != 0) {
throw new ZipException("Invalid General Purpose Bit Flag: " + gpbf);
@@ -294,14 +301,13 @@
// Skip the variable-size file name and extra field data.
rafStream.skip(fileNameLength + extraFieldLength);
- // The compressed or stored file data follows immediately after.
- if (entry.compressionMethod == ZipEntry.DEFLATED) {
- rafStream.length = rafStream.offset + entry.compressedSize;
+ if (entry.compressionMethod == ZipEntry.STORED) {
+ rafStream.endOffset = rafStream.offset + entry.size;
+ return rafStream;
+ } else {
+ rafStream.endOffset = rafStream.offset + entry.compressedSize;
int bufSize = Math.max(1024, (int) Math.min(entry.getSize(), 65535L));
return new ZipInflaterInputStream(rafStream, new Inflater(true), bufSize, entry);
- } else {
- rafStream.length = rafStream.offset + entry.size;
- return rafStream;
}
}
}
@@ -349,21 +355,26 @@
throw new ZipException("File too short to be a zip file: " + raf.length());
}
+ raf.seek(0);
+ final int headerMagic = Integer.reverseBytes(raf.readInt());
+ if (headerMagic != LOCSIG) {
+ throw new ZipException("Not a zip archive");
+ }
+
long stopOffset = scanOffset - 65536;
if (stopOffset < 0) {
stopOffset = 0;
}
- final int ENDHEADERMAGIC = 0x06054b50;
while (true) {
raf.seek(scanOffset);
- if (Integer.reverseBytes(raf.readInt()) == ENDHEADERMAGIC) {
+ if (Integer.reverseBytes(raf.readInt()) == ENDSIG) {
break;
}
scanOffset--;
if (scanOffset < stopOffset) {
- throw new ZipException("EOCD not found; not a zip file?");
+ throw new ZipException("End Of Central Directory signature not found");
}
}
@@ -383,7 +394,7 @@
int commentLength = it.readShort() & 0xffff;
if (numEntries != totalNumEntries || diskNumber != 0 || diskWithCentralDir != 0) {
- throw new ZipException("spanned archives not supported");
+ throw new ZipException("Spanned archives not supported");
}
if (commentLength > 0) {
@@ -401,6 +412,9 @@
byte[] hdrBuf = new byte[CENHDR]; // Reuse the same buffer for each entry.
for (int i = 0; i < numEntries; ++i) {
ZipEntry newEntry = new ZipEntry(hdrBuf, bufferedStream);
+ if (newEntry.localHeaderRelOffset >= centralDirOffset) {
+ throw new ZipException("Local file header offset is after central directory");
+ }
String entryName = newEntry.getName();
if (entries.put(entryName, newEntry) != null) {
throw new ZipException("Duplicate entry name: " + entryName);
@@ -408,6 +422,11 @@
}
}
+ static void throwZipException(String msg, int magic) throws ZipException {
+ final String hexString = IntegralToString.intToHexString(magic, true, 8);
+ throw new ZipException(msg + " signature not found; was " + hexString);
+ }
+
/**
* Wrap a stream around a RandomAccessFile. The RandomAccessFile is shared
* among all streams returned by getInputStream(), so we have to synchronize
@@ -418,17 +437,17 @@
*/
static class RAFStream extends InputStream {
private final RandomAccessFile sharedRaf;
- private long length;
+ private long endOffset;
private long offset;
public RAFStream(RandomAccessFile raf, long initialOffset) throws IOException {
sharedRaf = raf;
offset = initialOffset;
- length = raf.length();
+ endOffset = raf.length();
}
@Override public int available() throws IOException {
- return (offset < length ? 1 : 0);
+ return (offset < endOffset ? 1 : 0);
}
@Override public int read() throws IOException {
@@ -437,10 +456,11 @@
@Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
synchronized (sharedRaf) {
- sharedRaf.seek(offset);
- if (byteCount > length - offset) {
- byteCount = (int) (length - offset);
+ final long length = endOffset - offset;
+ if (byteCount > length) {
+ byteCount = (int) length;
}
+ sharedRaf.seek(offset);
int count = sharedRaf.read(buffer, byteOffset, byteCount);
if (count > 0) {
offset += count;
@@ -452,8 +472,8 @@
}
@Override public long skip(long byteCount) throws IOException {
- if (byteCount > length - offset) {
- byteCount = length - offset;
+ if (byteCount > endOffset - offset) {
+ byteCount = endOffset - offset;
}
offset += byteCount;
return byteCount;
@@ -461,7 +481,7 @@
public int fill(Inflater inflater, int nativeEndBufSize) throws IOException {
synchronized (sharedRaf) {
- int len = Math.min((int) (length - offset), nativeEndBufSize);
+ int len = Math.min((int) (endOffset - offset), nativeEndBufSize);
int cnt = inflater.setFileInput(sharedRaf.getFD(), offset, nativeEndBufSize);
// setFileInput read from the file, so we need to get the OS and RAFStream back
// in sync...
@@ -481,8 +501,19 @@
}
@Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
- int i = super.read(buffer, byteOffset, byteCount);
- if (i != -1) {
+ final int i;
+ try {
+ i = super.read(buffer, byteOffset, byteCount);
+ } catch (IOException e) {
+ throw new IOException("Error reading data for " + entry.getName() + " near offset "
+ + bytesRead, e);
+ }
+ if (i == -1) {
+ if (entry.size != bytesRead) {
+ throw new IOException("Size mismatch on inflated file: " + bytesRead + " vs "
+ + entry.size);
+ }
+ } else {
bytesRead += i;
}
return i;
diff --git a/luni/src/main/java/javax/crypto/CipherInputStream.java b/luni/src/main/java/javax/crypto/CipherInputStream.java
index a59a425..f2f59c1 100644
--- a/luni/src/main/java/javax/crypto/CipherInputStream.java
+++ b/luni/src/main/java/javax/crypto/CipherInputStream.java
@@ -104,7 +104,7 @@
try {
outputLength = cipher.doFinal(outputBuffer, 0);
} catch (Exception e) {
- throw new IOException(e.getMessage());
+ throw new IOException("Error while finalizing cipher", e);
}
finished = true;
break;
diff --git a/luni/src/main/java/libcore/icu/DateIntervalFormat.java b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
index a3e1e5e..ab9085f 100644
--- a/luni/src/main/java/libcore/icu/DateIntervalFormat.java
+++ b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
@@ -19,6 +19,7 @@
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
+import libcore.util.BasicLruCache;
/**
* Exposes icu4c's DateIntervalFormat.
@@ -27,22 +28,37 @@
// These are all public API in DateUtils. There are others, but they're either for use with
// other methods (like FORMAT_ABBREV_RELATIVE), don't internationalize (like FORMAT_CAP_AMPM),
- // or have never been implemented anyway (like FORMAT_NO_YEAR).
- public static final int FORMAT_SHOW_TIME = 0x00001;
- public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
- public static final int FORMAT_SHOW_YEAR = 0x00004;
- public static final int FORMAT_SHOW_DATE = 0x00010;
- public static final int FORMAT_NO_MONTH_DAY = 0x00020;
- public static final int FORMAT_12HOUR = 0x00040;
- public static final int FORMAT_24HOUR = 0x00080;
- public static final int FORMAT_UTC = 0x02000;
- public static final int FORMAT_ABBREV_TIME = 0x04000;
+ // or have never been implemented anyway.
+ public static final int FORMAT_SHOW_TIME = 0x00001;
+ public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
+ public static final int FORMAT_SHOW_YEAR = 0x00004;
+ public static final int FORMAT_NO_YEAR = 0x00008;
+ public static final int FORMAT_SHOW_DATE = 0x00010;
+ public static final int FORMAT_NO_MONTH_DAY = 0x00020;
+ public static final int FORMAT_12HOUR = 0x00040;
+ public static final int FORMAT_24HOUR = 0x00080;
+ public static final int FORMAT_UTC = 0x02000;
+ public static final int FORMAT_ABBREV_TIME = 0x04000;
public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
- public static final int FORMAT_ABBREV_MONTH = 0x10000;
- public static final int FORMAT_NUMERIC_DATE = 0x20000;
- public static final int FORMAT_ABBREV_ALL = 0x80000;
+ public static final int FORMAT_ABBREV_MONTH = 0x10000;
+ public static final int FORMAT_NUMERIC_DATE = 0x20000;
+ public static final int FORMAT_ABBREV_ALL = 0x80000;
- // TODO: check whether icu4c's DateIntervalFormat is expensive enough to warrant a native peer.
+ private static final int DAY_IN_MS = 24 * 60 * 60 * 1000;
+ private static final int EPOCH_JULIAN_DAY = 2440588;
+
+ private static final FormatterCache CACHED_FORMATTERS = new FormatterCache();
+
+ static class FormatterCache extends BasicLruCache<String, Long> {
+ FormatterCache() {
+ super(8);
+ }
+
+ protected void entryEvicted(String key, Long value) {
+ destroyDateIntervalFormat(value);
+ }
+ };
+
private DateIntervalFormat() {
}
@@ -58,11 +74,6 @@
// This is our slightly more sensible internal API. (A truly sane replacement would take a
// skeleton instead of int flags.)
public static String formatDateRange(Locale locale, TimeZone tz, long startMs, long endMs, int flags) {
- String skeleton = toSkeleton(tz, startMs, endMs, flags);
- return formatDateInterval(skeleton, locale.toString(), tz.getID(), startMs, endMs);
- }
-
- private static String toSkeleton(TimeZone tz, long startMs, long endMs, int flags) {
Calendar startCalendar = Calendar.getInstance(tz);
startCalendar.setTimeInMillis(startMs);
@@ -74,6 +85,36 @@
endCalendar.setTimeInMillis(endMs);
}
+ boolean endsAtMidnight = isMidnight(endCalendar);
+
+ // If we're not showing the time or the start and end times are on the same day, and the
+ // end time is midnight, fudge the end date so we don't count the day that's about to start.
+ // This is not the behavior of icu4c's DateIntervalFormat, but it's the historical behavior
+ // of Android's DateUtils.formatDateRange.
+ if (startMs != endMs && endsAtMidnight &&
+ ((flags & FORMAT_SHOW_TIME) == 0 || julianDay(startCalendar) == julianDay(endCalendar))) {
+ endCalendar.roll(Calendar.DAY_OF_MONTH, false);
+ endMs -= DAY_IN_MS;
+ }
+
+ String skeleton = toSkeleton(startCalendar, endCalendar, flags);
+ synchronized (CACHED_FORMATTERS) {
+ return formatDateInterval(getFormatter(skeleton, locale.toString(), tz.getID()), startMs, endMs);
+ }
+ }
+
+ private static long getFormatter(String skeleton, String localeName, String tzName) {
+ String key = skeleton + "\t" + localeName + "\t" + tzName;
+ Long formatter = CACHED_FORMATTERS.get(key);
+ if (formatter != null) {
+ return formatter;
+ }
+ long address = createDateIntervalFormat(skeleton, localeName, tzName);
+ CACHED_FORMATTERS.put(key, address);
+ return address;
+ }
+
+ private static String toSkeleton(Calendar startCalendar, Calendar endCalendar, int flags) {
if ((flags & FORMAT_ABBREV_ALL) != 0) {
flags |= FORMAT_ABBREV_MONTH | FORMAT_ABBREV_TIME | FORMAT_ABBREV_WEEKDAY;
}
@@ -96,8 +137,18 @@
} else if ((flags & FORMAT_12HOUR) != 0) {
timePart = "h";
}
- if ((flags & FORMAT_ABBREV_TIME) == 0 || !onTheHour(startCalendar) || !onTheHour(endCalendar)) {
- timePart = timePart + "m";
+
+ // If we've not been asked to abbreviate times, or we're using the 24-hour clock (where it
+ // never makes sense to leave out the minutes), include minutes. This gets us times like
+ // "4 PM" while avoiding times like "16" (for "16:00").
+ if ((flags & FORMAT_ABBREV_TIME) == 0 || (flags & FORMAT_24HOUR) != 0) {
+ timePart += "m";
+ } else {
+ // Otherwise, we're abbreviating a 12-hour time, and should only show the minutes
+ // if they're not both "00".
+ if (!(onTheHour(startCalendar) && onTheHour(endCalendar))) {
+ timePart = timePart + "m";
+ }
}
if (fallOnDifferentDates(startCalendar, endCalendar)) {
@@ -113,6 +164,17 @@
flags |= FORMAT_SHOW_DATE;
}
+ // If we've been asked to show the date, work out whether we think we should show the year.
+ if ((flags & FORMAT_SHOW_DATE) != 0) {
+ if ((flags & FORMAT_SHOW_YEAR) != 0) {
+ // The caller explicitly wants us to show the year.
+ } else if ((flags & FORMAT_NO_YEAR) != 0) {
+ // The caller explicitly doesn't want us to show the year, even if we otherwise would.
+ } else if (!fallInSameYear(startCalendar, endCalendar) || !isThisYear(startCalendar)) {
+ flags |= FORMAT_SHOW_YEAR;
+ }
+ }
+
StringBuilder builder = new StringBuilder();
if ((flags & (FORMAT_SHOW_DATE | FORMAT_NO_MONTH_DAY)) != 0) {
if ((flags & FORMAT_SHOW_YEAR) != 0) {
@@ -132,6 +194,13 @@
return builder.toString();
}
+ private static boolean isMidnight(Calendar c) {
+ return c.get(Calendar.HOUR_OF_DAY) == 0 &&
+ c.get(Calendar.MINUTE) == 0 &&
+ c.get(Calendar.SECOND) == 0 &&
+ c.get(Calendar.MILLISECOND) == 0;
+ }
+
private static boolean onTheHour(Calendar c) {
return c.get(Calendar.MINUTE) == 0 && c.get(Calendar.SECOND) == 0;
}
@@ -146,5 +215,21 @@
return c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH);
}
- private static native String formatDateInterval(String skeleton, String localeName, String timeZoneName, long fromDate, long toDate);
+ private static boolean fallInSameYear(Calendar c1, Calendar c2) {
+ return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR);
+ }
+
+ private static boolean isThisYear(Calendar c) {
+ Calendar now = Calendar.getInstance(c.getTimeZone());
+ return c.get(Calendar.YEAR) == now.get(Calendar.YEAR);
+ }
+
+ private static int julianDay(Calendar c) {
+ long utcMs = c.get(Calendar.MILLISECOND) + c.get(Calendar.ZONE_OFFSET);
+ return (int) (utcMs / DAY_IN_MS) + EPOCH_JULIAN_DAY;
+ }
+
+ private static native long createDateIntervalFormat(String skeleton, String localeName, String tzName);
+ private static native void destroyDateIntervalFormat(long address);
+ private static native String formatDateInterval(long address, long fromDate, long toDate);
}
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index 6a72d44..76d9c54 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -18,218 +18,228 @@
import java.util.LinkedHashSet;
import java.util.Locale;
+import libcore.util.BasicLruCache;
/**
* Makes ICU data accessible to Java.
*/
public final class ICU {
- /**
- * Cache for ISO language names.
- */
- private static String[] isoLanguages;
+ private static final BasicLruCache<String, String> CACHED_PATTERNS =
+ new BasicLruCache<String, String>(8);
- /**
- * Cache for ISO country names.
- */
- private static String[] isoCountries;
+ private static Locale[] availableLocalesCache;
- /**
- * Returns an array of ISO language names (two-letter codes), fetched either
- * from ICU's database or from our memory cache.
- *
- * @return The array.
- */
- public static String[] getISOLanguages() {
- if (isoLanguages == null) {
- isoLanguages = getISOLanguagesNative();
- }
- return isoLanguages.clone();
+ private static String[] isoCountries;
+
+ private static String[] isoLanguages;
+
+ /**
+ * Returns an array of two-letter ISO 639-1 language codes, either from ICU or our cache.
+ */
+ public static String[] getISOLanguages() {
+ if (isoLanguages == null) {
+ isoLanguages = getISOLanguagesNative();
}
+ return isoLanguages.clone();
+ }
- /**
- * Returns an array of ISO country names (two-letter codes), fetched either
- * from ICU's database or from our memory cache.
- *
- * @return The array.
- */
- public static String[] getISOCountries() {
- if (isoCountries == null) {
- isoCountries = getISOCountriesNative();
- }
- return isoCountries.clone();
+ /**
+ * Returns an array of two-letter ISO 3166 country codes, either from ICU or our cache.
+ */
+ public static String[] getISOCountries() {
+ if (isoCountries == null) {
+ isoCountries = getISOCountriesNative();
}
+ return isoCountries.clone();
+ }
- /**
- * Returns the appropriate {@code Locale} given a {@code String} of the form returned
- * by {@code toString}. This is very lenient, and doesn't care what's between the underscores:
- * this method can parse strings that {@code Locale.toString} won't produce.
- * Used to remove duplication.
- */
- public static Locale localeFromString(String localeName) {
- int first = localeName.indexOf('_');
- int second = localeName.indexOf('_', first + 1);
- if (first == -1) {
- // Language only ("ja").
- return new Locale(localeName);
- } else if (second == -1) {
- // Language and country ("ja_JP").
- return new Locale(localeName.substring(0, first), localeName.substring(first + 1));
- } else {
- // Language and country and variant ("ja_JP_TRADITIONAL").
- return new Locale(localeName.substring(0, first), localeName.substring(first + 1, second), localeName.substring(second + 1));
- }
+ /**
+ * Returns the appropriate {@code Locale} given a {@code String} of the form returned
+ * by {@code toString}. This is very lenient, and doesn't care what's between the underscores:
+ * this method can parse strings that {@code Locale.toString} won't produce.
+ * Used to remove duplication.
+ */
+ public static Locale localeFromString(String localeName) {
+ int first = localeName.indexOf('_');
+ int second = localeName.indexOf('_', first + 1);
+ if (first == -1) {
+ // Language only ("ja").
+ return new Locale(localeName);
+ } else if (second == -1) {
+ // Language and country ("ja_JP").
+ String language = localeName.substring(0, first);
+ String country = localeName.substring(first + 1);
+ return new Locale(language, country);
+ } else {
+ // Language and country and variant ("ja_JP_TRADITIONAL").
+ String language = localeName.substring(0, first);
+ String country = localeName.substring(first + 1, second);
+ String variant = localeName.substring(second + 1);
+ return new Locale(language, country, variant);
}
+ }
- public static Locale[] localesFromStrings(String[] localeNames) {
- // We need to remove duplicates caused by the conversion of "he" to "iw", et cetera.
- // Java needs the obsolete code, ICU needs the modern code, but we let ICU know about
- // both so that we never need to convert back when talking to it.
- LinkedHashSet<Locale> set = new LinkedHashSet<Locale>();
- for (String localeName : localeNames) {
- set.add(localeFromString(localeName));
- }
- return set.toArray(new Locale[set.size()]);
+ public static Locale[] localesFromStrings(String[] localeNames) {
+ // We need to remove duplicates caused by the conversion of "he" to "iw", et cetera.
+ // Java needs the obsolete code, ICU needs the modern code, but we let ICU know about
+ // both so that we never need to convert back when talking to it.
+ LinkedHashSet<Locale> set = new LinkedHashSet<Locale>();
+ for (String localeName : localeNames) {
+ set.add(localeFromString(localeName));
}
+ return set.toArray(new Locale[set.size()]);
+ }
- private static Locale[] availableLocalesCache;
- public static Locale[] getAvailableLocales() {
- if (availableLocalesCache == null) {
- availableLocalesCache = localesFromStrings(getAvailableLocalesNative());
- }
- return availableLocalesCache.clone();
+ public static Locale[] getAvailableLocales() {
+ if (availableLocalesCache == null) {
+ availableLocalesCache = localesFromStrings(getAvailableLocalesNative());
}
+ return availableLocalesCache.clone();
+ }
- public static Locale[] getAvailableBreakIteratorLocales() {
- return localesFromStrings(getAvailableBreakIteratorLocalesNative());
- }
+ public static Locale[] getAvailableBreakIteratorLocales() {
+ return localesFromStrings(getAvailableBreakIteratorLocalesNative());
+ }
- public static Locale[] getAvailableCalendarLocales() {
- return localesFromStrings(getAvailableCalendarLocalesNative());
- }
+ public static Locale[] getAvailableCalendarLocales() {
+ return localesFromStrings(getAvailableCalendarLocalesNative());
+ }
- public static Locale[] getAvailableCollatorLocales() {
- return localesFromStrings(getAvailableCollatorLocalesNative());
- }
+ public static Locale[] getAvailableCollatorLocales() {
+ return localesFromStrings(getAvailableCollatorLocalesNative());
+ }
- public static Locale[] getAvailableDateFormatLocales() {
- return localesFromStrings(getAvailableDateFormatLocalesNative());
- }
+ public static Locale[] getAvailableDateFormatLocales() {
+ return localesFromStrings(getAvailableDateFormatLocalesNative());
+ }
- public static Locale[] getAvailableDateFormatSymbolsLocales() {
- return getAvailableDateFormatLocales();
- }
+ public static Locale[] getAvailableDateFormatSymbolsLocales() {
+ return getAvailableDateFormatLocales();
+ }
- public static Locale[] getAvailableDecimalFormatSymbolsLocales() {
- return getAvailableNumberFormatLocales();
- }
+ public static Locale[] getAvailableDecimalFormatSymbolsLocales() {
+ return getAvailableNumberFormatLocales();
+ }
- public static Locale[] getAvailableNumberFormatLocales() {
- return localesFromStrings(getAvailableNumberFormatLocalesNative());
- }
+ public static Locale[] getAvailableNumberFormatLocales() {
+ return localesFromStrings(getAvailableNumberFormatLocalesNative());
+ }
- public static native String getBestDateTimePattern(String skeleton, String localeName);
-
- public static char[] getDateFormatOrder(String pattern) {
- char[] result = new char[3];
- int resultIndex = 0;
- boolean sawDay = false;
- boolean sawMonth = false;
- boolean sawYear = false;
-
- for (int i = 0; i < pattern.length(); ++i) {
- char ch = pattern.charAt(i);
- if (ch == 'd' || ch == 'L' || ch == 'M' || ch == 'y') {
- if (ch == 'd' && !sawDay) {
- result[resultIndex++] = 'd';
- sawDay = true;
- } else if ((ch == 'L' || ch == 'M') && !sawMonth) {
- result[resultIndex++] = 'M';
- sawMonth = true;
- } else if ((ch == 'y') && !sawYear) {
- result[resultIndex++] = 'y';
- sawYear = true;
- }
- } else if (ch == 'G') {
- // Ignore the era specifier, if present.
- } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
- throw new IllegalArgumentException("Bad pattern character '" + ch + "' in " + pattern);
- } else if (ch == '\'') {
- if (i < pattern.length() - 1 && pattern.charAt(i + 1) == '\'') {
- ++i;
- } else {
- i = pattern.indexOf('\'', i + 1);
- if (i == -1) {
- throw new IllegalArgumentException("Bad quoting in " + pattern);
- }
- ++i;
- }
- } else {
- // Ignore spaces and punctuation.
- }
+ public static String getBestDateTimePattern(String skeleton, String localeName) {
+ String key = skeleton + "\t" + localeName;
+ synchronized (CACHED_PATTERNS) {
+ String pattern = CACHED_PATTERNS.get(key);
+ if (pattern == null) {
+ pattern = getBestDateTimePatternNative(skeleton, localeName);
+ CACHED_PATTERNS.put(key, pattern);
}
- return result;
+ return pattern;
}
+ }
- /**
- * Returns the version of the CLDR data in use, such as "22.1.1".
- */
- public static native String getCldrVersion();
+ private static native String getBestDateTimePatternNative(String skeleton, String localeName);
- /**
- * Returns the icu4c version in use, such as "50.1.1".
- */
- public static native String getIcuVersion();
+ public static char[] getDateFormatOrder(String pattern) {
+ char[] result = new char[3];
+ int resultIndex = 0;
+ boolean sawDay = false;
+ boolean sawMonth = false;
+ boolean sawYear = false;
- /**
- * Returns the Unicode version our ICU supports, such as "6.2".
- */
- public static native String getUnicodeVersion();
-
- // --- Case mapping.
-
- public static native String toLowerCase(String s, String localeName);
- public static native String toUpperCase(String s, String localeName);
-
- // --- Errors.
-
- // Just the subset of error codes needed by CharsetDecoderICU/CharsetEncoderICU.
- public static final int U_ZERO_ERROR = 0;
- public static final int U_INVALID_CHAR_FOUND = 10;
- public static final int U_TRUNCATED_CHAR_FOUND = 11;
- public static final int U_ILLEGAL_CHAR_FOUND = 12;
- public static final int U_BUFFER_OVERFLOW_ERROR = 15;
-
- public static boolean U_FAILURE(int error) {
- return error > U_ZERO_ERROR;
+ for (int i = 0; i < pattern.length(); ++i) {
+ char ch = pattern.charAt(i);
+ if (ch == 'd' || ch == 'L' || ch == 'M' || ch == 'y') {
+ if (ch == 'd' && !sawDay) {
+ result[resultIndex++] = 'd';
+ sawDay = true;
+ } else if ((ch == 'L' || ch == 'M') && !sawMonth) {
+ result[resultIndex++] = 'M';
+ sawMonth = true;
+ } else if ((ch == 'y') && !sawYear) {
+ result[resultIndex++] = 'y';
+ sawYear = true;
+ }
+ } else if (ch == 'G') {
+ // Ignore the era specifier, if present.
+ } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
+ throw new IllegalArgumentException("Bad pattern character '" + ch + "' in " + pattern);
+ } else if (ch == '\'') {
+ if (i < pattern.length() - 1 && pattern.charAt(i + 1) == '\'') {
+ ++i;
+ } else {
+ i = pattern.indexOf('\'', i + 1);
+ if (i == -1) {
+ throw new IllegalArgumentException("Bad quoting in " + pattern);
+ }
+ ++i;
+ }
+ } else {
+ // Ignore spaces and punctuation.
+ }
}
+ return result;
+ }
- // --- Native methods accessing ICU's database.
+ /**
+ * Returns the version of the CLDR data in use, such as "22.1.1".
+ */
+ public static native String getCldrVersion();
- private static native String[] getAvailableBreakIteratorLocalesNative();
- private static native String[] getAvailableCalendarLocalesNative();
- private static native String[] getAvailableCollatorLocalesNative();
- private static native String[] getAvailableDateFormatLocalesNative();
- private static native String[] getAvailableLocalesNative();
- private static native String[] getAvailableNumberFormatLocalesNative();
+ /**
+ * Returns the icu4c version in use, such as "50.1.1".
+ */
+ public static native String getIcuVersion();
- public static native String[] getAvailableCurrencyCodes();
- public static native String getCurrencyCode(String countryCode);
- public static native String getCurrencyDisplayName(String locale, String currencyCode);
- public static native int getCurrencyFractionDigits(String currencyCode);
- public static native String getCurrencySymbol(String locale, String currencyCode);
+ /**
+ * Returns the Unicode version our ICU supports, such as "6.2".
+ */
+ public static native String getUnicodeVersion();
- public static native String getDisplayCountryNative(String countryCode, String locale);
- public static native String getDisplayLanguageNative(String languageCode, String locale);
- public static native String getDisplayVariantNative(String variantCode, String locale);
+ // --- Case mapping.
- public static native String getISO3CountryNative(String locale);
- public static native String getISO3LanguageNative(String locale);
+ public static native String toLowerCase(String s, String localeName);
+ public static native String toUpperCase(String s, String localeName);
- public static native String addLikelySubtags(String locale);
- public static native String getScript(String locale);
+ // --- Errors.
- private static native String[] getISOLanguagesNative();
- private static native String[] getISOCountriesNative();
+ // Just the subset of error codes needed by CharsetDecoderICU/CharsetEncoderICU.
+ public static final int U_ZERO_ERROR = 0;
+ public static final int U_INVALID_CHAR_FOUND = 10;
+ public static final int U_TRUNCATED_CHAR_FOUND = 11;
+ public static final int U_ILLEGAL_CHAR_FOUND = 12;
+ public static final int U_BUFFER_OVERFLOW_ERROR = 15;
- static native boolean initLocaleDataImpl(String locale, LocaleData result);
+ public static boolean U_FAILURE(int error) {
+ return error > U_ZERO_ERROR;
+ }
+
+ // --- Native methods accessing ICU's database.
+
+ private static native String[] getAvailableBreakIteratorLocalesNative();
+ private static native String[] getAvailableCalendarLocalesNative();
+ private static native String[] getAvailableCollatorLocalesNative();
+ private static native String[] getAvailableDateFormatLocalesNative();
+ private static native String[] getAvailableLocalesNative();
+ private static native String[] getAvailableNumberFormatLocalesNative();
+
+ public static native String[] getAvailableCurrencyCodes();
+ public static native String getCurrencyCode(String countryCode);
+ public static native String getCurrencyDisplayName(String locale, String currencyCode);
+ public static native int getCurrencyFractionDigits(String currencyCode);
+ public static native String getCurrencySymbol(String locale, String currencyCode);
+
+ public static native String getDisplayCountryNative(String countryCode, String locale);
+ public static native String getDisplayLanguageNative(String languageCode, String locale);
+ public static native String getDisplayVariantNative(String variantCode, String locale);
+
+ public static native String getISO3CountryNative(String locale);
+ public static native String getISO3LanguageNative(String locale);
+
+ public static native String addLikelySubtags(String locale);
+ public static native String getScript(String locale);
+
+ private static native String[] getISOLanguagesNative();
+ private static native String[] getISOCountriesNative();
+
+ static native boolean initLocaleDataNative(String locale, LocaleData result);
}
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index a6d700f..f00c30f 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -171,9 +171,15 @@
private static LocaleData initLocaleData(Locale locale) {
LocaleData localeData = new LocaleData();
- if (!ICU.initLocaleDataImpl(locale.toString(), localeData)) {
+ if (!ICU.initLocaleDataNative(locale.toString(), localeData)) {
throw new AssertionError("couldn't initialize LocaleData for locale " + locale);
}
+
+ // Get the "h:mm a" and "HH:mm" 12- and 24-hour time format strings.
+ localeData.timeFormat12 = ICU.getBestDateTimePattern("hm", locale.toString());
+ localeData.timeFormat24 = ICU.getBestDateTimePattern("Hm", locale.toString());
+
+ // Fix up a couple of patterns.
if (localeData.fullTimeFormat != null) {
// There are some full time format patterns in ICU that use the pattern character 'v'.
// Java doesn't accept this, so we replace it with 'z' which has about the same result
diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java
index f7cc41f..10ef671 100644
--- a/luni/src/main/java/libcore/io/IoUtils.java
+++ b/luni/src/main/java/libcore/io/IoUtils.java
@@ -18,10 +18,11 @@
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InterruptedIOException;
-import java.io.RandomAccessFile;
import java.net.Socket;
+import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import static libcore.io.OsConstants.*;
@@ -102,33 +103,15 @@
/**
* Returns the contents of 'path' as a byte array.
*/
- public static byte[] readFileAsByteArray(String path) throws IOException {
- return readFileAsBytes(path).toByteArray();
+ public static byte[] readFileAsByteArray(String absolutePath) throws IOException {
+ return new FileReader(absolutePath).readFully().toByteArray();
}
/**
* Returns the contents of 'path' as a string. The contents are assumed to be UTF-8.
*/
- public static String readFileAsString(String path) throws IOException {
- return readFileAsBytes(path).toString(StandardCharsets.UTF_8);
- }
-
- private static UnsafeByteSequence readFileAsBytes(String path) throws IOException {
- RandomAccessFile f = null;
- try {
- f = new RandomAccessFile(path, "r");
- UnsafeByteSequence bytes = new UnsafeByteSequence((int) f.length());
- byte[] buffer = new byte[8192];
- while (true) {
- int byteCount = f.read(buffer);
- if (byteCount == -1) {
- return bytes;
- }
- bytes.write(buffer, 0, byteCount);
- }
- } finally {
- IoUtils.closeQuietly(f);
- }
+ public static String readFileAsString(String absolutePath) throws IOException {
+ return new FileReader(absolutePath).readFully().toString(StandardCharsets.UTF_8);
}
/**
@@ -193,4 +176,100 @@
// TODO: set InterruptedIOException.bytesTransferred
throw new InterruptedIOException();
}
+
+ /**
+ * A convenience class for reading the contents of a file into a {@code String}
+ * or a {@code byte[]}. This class attempts to minimize the number of allocations
+ * and copies required to read this data.
+ *
+ * For the case where we know the "true" length of a file (most ordinary files)
+ * we allocate exactly one byte[] and copy data into that. Calls to
+ * {@link #toByteArray} will then return the internal array and <b>not</b> a copy.
+ *
+ * <b>Note that an absolute path must be supplied. Expect your reads to fail
+ * if one isn't.</b>
+ */
+ private static class FileReader {
+ private FileDescriptor fd;
+ private boolean unknownLength;
+
+ private byte[] bytes;
+ private int count;
+
+ public FileReader(String absolutePath) throws IOException {
+ // We use IoBridge.open because callers might differentiate
+ // between a FileNotFoundException and a general IOException.
+ //
+ // NOTE: This costs us an additional call to fstat(2) to test whether
+ // "absolutePath" is a directory or not. We can eliminate it
+ // at the cost of copying some code from IoBridge.open.
+ try {
+ fd = IoBridge.open(absolutePath, O_RDONLY);
+ } catch (FileNotFoundException fnfe) {
+ throw fnfe;
+ }
+
+ int capacity;
+ try {
+ final StructStat stat = Libcore.os.fstat(fd);
+ // Like RAF & other APIs, we assume that the file size fits
+ // into a 32 bit integer.
+ capacity = (int) stat.st_size;
+ if (capacity == 0) {
+ unknownLength = true;
+ capacity = 8192;
+ }
+ } catch (ErrnoException exception) {
+ closeQuietly(fd);
+ throw exception.rethrowAsIOException();
+ }
+
+ bytes = new byte[capacity];
+ }
+
+ public FileReader readFully() throws IOException {
+ int read;
+ int capacity = bytes.length;
+ try {
+ while ((read = Libcore.os.read(fd, bytes, count, capacity - count)) != 0) {
+ count += read;
+ if (count == capacity) {
+ if (unknownLength) {
+ // If we don't know the length of this file, we need to continue
+ // reading until we reach EOF. Double the capacity in preparation.
+ final int newCapacity = capacity * 2;
+ byte[] newBytes = new byte[newCapacity];
+ System.arraycopy(bytes, 0, newBytes, 0, capacity);
+ bytes = newBytes;
+ capacity = newCapacity;
+ } else {
+ // We know the length of this file and we've read the right number
+ // of bytes from it, return.
+ break;
+ }
+ }
+ }
+
+ return this;
+ } catch (ErrnoException e) {
+ throw e.rethrowAsIOException();
+ } finally {
+ closeQuietly(fd);
+ }
+ }
+
+ @FindBugsSuppressWarnings("EI_EXPOSE_REP")
+ public byte[] toByteArray() {
+ if (count == bytes.length) {
+ return bytes;
+ }
+ byte[] result = new byte[count];
+ System.arraycopy(bytes, 0, result, 0, count);
+ return result;
+ }
+
+ public String toString(Charset cs) {
+ return new String(bytes, 0, count, cs);
+ }
+ }
}
diff --git a/luni/src/main/java/libcore/net/MimeUtils.java b/luni/src/main/java/libcore/net/MimeUtils.java
index 6e8c168..aaa5670 100644
--- a/luni/src/main/java/libcore/net/MimeUtils.java
+++ b/luni/src/main/java/libcore/net/MimeUtils.java
@@ -61,6 +61,7 @@
add("application/pgp-keys", "key");
add("application/pgp-signature", "pgp");
add("application/pics-rules", "prf");
+ add("application/pkix-cert", "cer");
add("application/rar", "rar");
add("application/rdf+xml", "rdf");
add("application/rss+xml", "rss");
@@ -182,6 +183,7 @@
add("application/x-nwc", "nwc");
add("application/x-object", "o");
add("application/x-oz-application", "oza");
+ add("application/x-pem-file", "pem");
add("application/x-pkcs12", "p12");
add("application/x-pkcs12", "pfx");
add("application/x-pkcs7-certreqresp", "p7r");
@@ -205,6 +207,7 @@
add("application/x-webarchive-xml", "webarchivexml");
add("application/x-x509-ca-cert", "crt");
add("application/x-x509-user-cert", "crt");
+ add("application/x-x509-server-cert", "crt");
add("application/x-xcf", "xcf");
add("application/x-xfig", "fig");
add("application/xhtml+xml", "xhtml");
diff --git a/luni/src/main/java/libcore/reflect/AnnotationAccess.java b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
index fe740de..4e34284 100644
--- a/luni/src/main/java/libcore/reflect/AnnotationAccess.java
+++ b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
@@ -187,11 +187,25 @@
Dex dex = dexClass.getDex();
int annotationTypeIndex = getTypeIndex(dex, annotationClass);
if (annotationTypeIndex == -1) {
- return null; // the dex file doesn't use this annotation
+ return null; // The dex file doesn't use this annotation.
}
int annotationSetOffset = getAnnotationSetOffset(element);
- return getAnnotationFromAnnotationSet(dex, annotationSetOffset, annotationTypeIndex);
+ if (annotationSetOffset == 0) {
+ return null; // no annotation
+ }
+
+ Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item
+ for (int i = 0, size = setIn.readInt(); i < size; i++) {
+ int annotationOffset = setIn.readInt();
+ Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
+ com.android.dex.Annotation candidate = annotationIn.readAnnotation();
+ if (candidate.getTypeIndex() == annotationTypeIndex) {
+ return candidate;
+ }
+ }
+
+ return null; // This set doesn't contain the annotation.
}
/**
@@ -199,7 +213,7 @@
*/
private static int getAnnotationSetOffset(AnnotatedElement element) {
Class<?> dexClass = getDexClass(element);
- int directoryOffset = getDirectoryOffset(dexClass);
+ int directoryOffset = dexClass.getDexAnnotationDirectoryOffset();
if (directoryOffset == 0) {
return 0; // nothing on this class has annotations
}
@@ -255,38 +269,32 @@
Dex dex = declaringClass.getDex();
int declaringClassIndex = getTypeIndex(dex, declaringClass);
int typeIndex = getTypeIndex(dex, type);
- int nameIndex = getStringIndex(dex, name);
+ int nameIndex = dex.findStringIndex(name);
FieldId fieldId = new FieldId(dex, declaringClassIndex, typeIndex, nameIndex);
- return Collections.binarySearch(dex.fieldIds(), fieldId);
+ return dex.findFieldIndex(fieldId);
}
public static int getMethodIndex(Class<?> declaringClass, String name, int protoIndex) {
Dex dex = declaringClass.getDex();
int declaringClassIndex = getTypeIndex(dex, declaringClass);
- int nameIndex = getStringIndex(dex, name);
+ int nameIndex = dex.findStringIndex(name);
MethodId methodId = new MethodId(dex, declaringClassIndex, protoIndex, nameIndex);
- return Collections.binarySearch(dex.methodIds(), methodId);
+ return dex.findMethodIndex(methodId);
}
/**
* Returns the parameter annotations on {@code member}.
*/
- public static Annotation[][] getParameterAnnotations(Member member) {
- Class<?> declaringClass = member.getDeclaringClass();
+ public static Annotation[][] getParameterAnnotations(Class<?> declaringClass,
+ int methodDexIndex) {
Dex dex = declaringClass.getDex();
- int methodDexIndex;
- if (member instanceof Method) {
- methodDexIndex = ((Method) member).getDexMethodIndex();
- } else {
- methodDexIndex = ((Constructor<?>) member).getDexMethodIndex();
- }
int protoIndex = dex.methodIds().get(methodDexIndex).getProtoIndex();
ProtoId proto = dex.protoIds().get(protoIndex);
TypeList parametersList = dex.readTypeList(proto.getParametersOffset());
short[] types = parametersList.getTypes();
int typesCount = types.length;
- int directoryOffset = getDirectoryOffset(declaringClass);
+ int directoryOffset = declaringClass.getDexAnnotationDirectoryOffset();
if (directoryOffset == 0) {
return new Annotation[typesCount][0]; // nothing on this class has annotations
}
@@ -358,7 +366,7 @@
throw new AssertionError("annotation value type != annotation class");
}
- int methodNameIndex = Collections.binarySearch(dex.strings(), method.getName());
+ int methodNameIndex = dex.findStringIndex(method.getName());
for (int i = 0; i < fieldCount; i++) {
int candidateNameIndex = reader.readAnnotationName();
if (candidateNameIndex == methodNameIndex) {
@@ -389,7 +397,7 @@
if (reader == null) {
return null;
}
- return indexToType(c, dex, reader.readType());
+ return c.getDexCacheType(dex, reader.readType());
}
public static AccessibleObject getEnclosingMethodOrConstructor(Class<?> c) {
@@ -529,47 +537,21 @@
* was derived.
*/
+ /** Find dex's type index for the class c */
private static int getTypeIndex(Dex dex, Class<?> c) {
- return dex == c.getDex() ? c.getTypeIndex() : computeTypeIndex(dex, c);
- }
-
- public static int computeTypeIndex(Dex dex, Class<?> c) {
+ if (dex == c.getDex()) {
+ return c.getDexTypeIndex();
+ }
if (dex == null) {
return -1;
}
- int typeIndex = Collections.binarySearch(dex.typeNames(), InternalNames.getInternalName(c));
+ int typeIndex = dex.findTypeIndex(InternalNames.getInternalName(c));
if (typeIndex < 0) {
typeIndex = -1;
}
return typeIndex;
}
- private static int getStringIndex(Dex dex, String string) {
- return Collections.binarySearch(dex.strings(), string);
- }
-
- private static int getDirectoryOffset(Class<?> c) {
- return c.getAnnotationDirectoryOffset();
- }
-
- private static com.android.dex.Annotation getAnnotationFromAnnotationSet(
- Dex dex, int annotationSetOffset, int annotationType) {
- if (annotationSetOffset == 0) {
- return null; // no annotation
- }
-
- Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item
- for (int i = 0, size = setIn.readInt(); i < size; i++) {
- int annotationOffset = setIn.readInt();
- Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
- com.android.dex.Annotation candidate = annotationIn.readAnnotation();
- if (candidate.getTypeIndex() == annotationType) {
- return candidate;
- }
- }
-
- return null; // this set doesn't carry the annotation
- }
private static EncodedValueReader getAnnotationReader(
Dex dex, AnnotatedElement element, String annotationName, int expectedFieldCount) {
@@ -578,16 +560,28 @@
return null; // no annotations on the class
}
- int annotationTypeIndex = Collections.binarySearch(dex.typeNames(), annotationName);
- com.android.dex.Annotation annotation = getAnnotationFromAnnotationSet(
- dex, annotationSetOffset, annotationTypeIndex);
+ Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item
+ com.android.dex.Annotation annotation = null;
+ // TODO: is it better to compute the index of the annotation name in the dex file and check
+ // indices below?
+ for (int i = 0, size = setIn.readInt(); i < size; i++) {
+ int annotationOffset = setIn.readInt();
+ Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
+ com.android.dex.Annotation candidate = annotationIn.readAnnotation();
+ String candidateAnnotationName = dex.typeNames().get(candidate.getTypeIndex());
+ if (annotationName.equals(candidateAnnotationName)) {
+ annotation = candidate;
+ break;
+ }
+ }
if (annotation == null) {
return null; // no annotation
}
EncodedValueReader reader = annotation.getReader();
int fieldCount = reader.readAnnotation();
- if (reader.getAnnotationType() != annotationTypeIndex) {
+ String readerAnnotationName = dex.typeNames().get(reader.getAnnotationType());
+ if (!readerAnnotationName.equals(annotationName)) {
throw new AssertionError();
}
if (fieldCount != expectedFieldCount) {
@@ -615,8 +609,8 @@
int typeIndex) {
try {
@SuppressWarnings("unchecked") // we do a runtime check
- Class<? extends Annotation> result = (Class<? extends Annotation>) indexToType(context,
- dex, typeIndex);
+ Class<? extends Annotation> result =
+ (Class<? extends Annotation>) context.getDexCacheType(dex, typeIndex);
if (!result.isAnnotation()) {
throw new IncompatibleClassChangeError("Expected annotation: " + result.getName());
}
@@ -626,65 +620,23 @@
}
}
- private static Class<?> indexToType(Class<?> context, Dex dex, int typeIndex) {
- String internalName = dex.typeNames().get(typeIndex);
- return InternalNames.getClass(context.getClassLoader(), internalName);
- }
-
private static AccessibleObject indexToMethod(Class<?> context, Dex dex, int methodIndex) {
- MethodId methodId = dex.methodIds().get(methodIndex);
- Class<?> declaringClass = indexToType(context, dex, methodId.getDeclaringClassIndex());
- String name = dex.strings().get(methodId.getNameIndex());
- Class<?>[] parametersArray = protoIndexToParameters(context, dex, methodId.getProtoIndex());
- try {
- return name.equals("<init>")
- ? declaringClass.getDeclaredConstructor(parametersArray)
- : declaringClass.getDeclaredMethod(name, parametersArray);
- } catch (NoSuchMethodException e) {
- throw new IncompatibleClassChangeError("Couldn't find " + declaringClass.getName()
- + "." + name + Arrays.toString(parametersArray));
- }
- }
-
- public static Class<?>[] protoIndexToParameters(Class<?> context, Dex dex, int protoIndex) {
- ProtoId proto = dex.protoIds().get(protoIndex);
- TypeList parametersList = dex.readTypeList(proto.getParametersOffset());
- short[] types = parametersList.getTypes();
+ Class<?> declaringClass =
+ context.getDexCacheType(dex, dex.declaringClassIndexFromMethodIndex(methodIndex));
+ String name = context.getDexCacheString(dex, dex.nameIndexFromMethodIndex(methodIndex));
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(methodIndex);
Class<?>[] parametersArray = new Class[types.length];
for (int i = 0; i < types.length; i++) {
- parametersArray[i] = indexToType(context, dex, types[i]);
+ parametersArray[i] = context.getDexCacheType(dex, types[i]);
}
- return parametersArray;
- }
-
- public static Class<?>[] typeIndexToInterfaces(Class<?> context, Dex dex, int typeIndex) {
- ClassDef def = getClassDef(dex, typeIndex);
- if (def == null) {
- return EmptyArray.CLASS;
+ try {
+ return name.equals("<init>")
+ ? declaringClass.getDeclaredConstructor(parametersArray)
+ : declaringClass.getDeclaredMethod(name, parametersArray);
+ } catch (NoSuchMethodException e) {
+ throw new IncompatibleClassChangeError("Couldn't find " + declaringClass.getName()
+ + "." + name + Arrays.toString(parametersArray));
}
- short[] interfaces = def.getInterfaces();
- Class<?>[] result = new Class<?>[interfaces.length];
- for (int i = 0; i < interfaces.length; i++) {
- result[i] = indexToType(context, dex, interfaces[i]);
- }
- return result;
- }
-
- public static int typeIndexToAnnotationDirectoryOffset(Dex dex, int typeIndex) {
- ClassDef def = getClassDef(dex, typeIndex);
- return def == null ? 0 : def.getAnnotationsOffset();
- }
-
- private static ClassDef getClassDef(Dex dex, int typeIndex) {
- if (typeIndex == -1) {
- return null;
- }
- for (ClassDef def : dex.classDefs()) {
- if (def.getTypeIndex() == typeIndex) {
- return def;
- }
- }
- throw new AssertionError();
}
private static List<Annotation> annotationSetToAnnotations(Class<?> context, int offset) {
@@ -722,7 +674,7 @@
private static <A extends Annotation> A toAnnotationInstance(Class<?> context, Dex dex,
Class<A> annotationClass, EncodedValueReader reader) {
int fieldCount = reader.readAnnotation();
- if (annotationClass != indexToType(context, dex, reader.getAnnotationType())) {
+ if (annotationClass != context.getDexCacheType(dex, reader.getAnnotationType())) {
throw new AssertionError("annotation value type != return type");
}
AnnotationMember[] members = new AnnotationMember[fieldCount];
@@ -756,20 +708,30 @@
} else if (type.isEnum()) {
int fieldIndex = reader.readEnum();
FieldId fieldId = dex.fieldIds().get(fieldIndex);
- String enumName = dex.strings().get(fieldId.getNameIndex());
- @SuppressWarnings({"unchecked", "rawtypes"}) // Class.isEnum is the runtime check
- Class<? extends Enum> enumType = (Class<? extends Enum>) type;
- return Enum.valueOf(enumType, enumName);
+ String fieldName = dex.strings().get(fieldId.getNameIndex());
+ Field field;
+ try {
+ field = type.getDeclaredField(fieldName);
+ return field.get(null);
+ } catch (NoSuchFieldException e) {
+ NoSuchFieldError error = new NoSuchFieldError();
+ error.initCause(e);
+ throw error;
+ } catch (IllegalAccessException e) {
+ IllegalAccessError error = new IllegalAccessError();
+ error.initCause(e);
+ throw error;
+ }
} else if (type.isAnnotation()) {
@SuppressWarnings("unchecked") // Class.isAnnotation is the runtime check
Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) type;
return toAnnotationInstance(context, dex, annotationClass, reader);
} else if (type == String.class) {
int index = reader.readString();
- return dex.strings().get(index);
+ return context.getDexCacheString(dex, index);
} else if (type == Class.class) {
int index = reader.readType();
- return indexToType(context, dex, index);
+ return context.getDexCacheType(dex, index);
} else if (type == byte.class) {
return reader.readByte();
} else if (type == short.class) {
diff --git a/luni/src/main/java/libcore/reflect/GenericSignatureParser.java b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
index 0c94eba..5e86c49 100644
--- a/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
+++ b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
@@ -22,6 +22,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
+import libcore.util.EmptyArray;
/**
* Implements a parser for the generics signature attribute.
@@ -119,19 +120,23 @@
* @param genericDecl the GenericDeclaration calling this method
* @param signature the generic signature of the class
*/
- public void parseForClass(GenericDeclaration genericDecl,
- String signature) {
+ public void parseForClass(GenericDeclaration genericDecl, String signature) {
setInput(genericDecl, signature);
if (!eof) {
parseClassSignature();
} else {
if(genericDecl instanceof Class) {
Class c = (Class) genericDecl;
- this.formalTypeParameters = ListOfVariables.EMPTY;
+ this.formalTypeParameters = EmptyArray.TYPE_VARIABLE;
this.superclassType = c.getSuperclass();
- this.interfaceTypes = new ListOfTypes(c.getInterfaces());
+ Class<?>[] interfaces = c.getInterfaces();
+ if (interfaces.length == 0) {
+ this.interfaceTypes = ListOfTypes.EMPTY;
+ } else {
+ this.interfaceTypes = new ListOfTypes(interfaces);
+ }
} else {
- this.formalTypeParameters = ListOfVariables.EMPTY;
+ this.formalTypeParameters = EmptyArray.TYPE_VARIABLE;
this.superclassType = Object.class;
this.interfaceTypes = ListOfTypes.EMPTY;
}
@@ -152,9 +157,19 @@
parseMethodTypeSignature(rawExceptionTypes);
} else {
Method m = (Method) genericDecl;
- this.formalTypeParameters = ListOfVariables.EMPTY;
- this.parameterTypes = new ListOfTypes(m.getParameterTypes());
- this.exceptionTypes = new ListOfTypes(m.getExceptionTypes());
+ this.formalTypeParameters = EmptyArray.TYPE_VARIABLE;
+ Class<?>[] parameterTypes = m.getParameterTypes();
+ if (parameterTypes.length == 0) {
+ this.parameterTypes = ListOfTypes.EMPTY;
+ } else {
+ this.parameterTypes = new ListOfTypes(parameterTypes);
+ }
+ Class<?>[] exceptionTypes = m.getExceptionTypes();
+ if (exceptionTypes.length == 0) {
+ this.exceptionTypes = ListOfTypes.EMPTY;
+ } else {
+ this.exceptionTypes = new ListOfTypes(exceptionTypes);
+ }
this.returnType = m.getReturnType();
}
}
@@ -173,9 +188,19 @@
parseMethodTypeSignature(rawExceptionTypes);
} else {
Constructor c = (Constructor) genericDecl;
- this.formalTypeParameters = ListOfVariables.EMPTY;
- this.parameterTypes = new ListOfTypes(c.getParameterTypes());
- this.exceptionTypes = new ListOfTypes(c.getExceptionTypes());
+ this.formalTypeParameters = EmptyArray.TYPE_VARIABLE;
+ Class<?>[] parameterTypes = c.getParameterTypes();
+ if (parameterTypes.length == 0) {
+ this.parameterTypes = ListOfTypes.EMPTY;
+ } else {
+ this.parameterTypes = new ListOfTypes(parameterTypes);
+ }
+ Class<?>[] exceptionTypes = c.getExceptionTypes();
+ if (exceptionTypes.length == 0) {
+ this.exceptionTypes = ListOfTypes.EMPTY;
+ } else {
+ this.exceptionTypes = new ListOfTypes(exceptionTypes);
+ }
}
}
@@ -449,7 +474,7 @@
}
}
- boolean isStopSymbol(char ch) {
+ static boolean isStopSymbol(char ch) {
switch (ch) {
case ':':
case '/':
@@ -472,7 +497,7 @@
char ch = buffer[pos];
if ((ch >= 'a') && (ch <= 'z') || (ch >= 'A') && (ch <= 'Z')
|| !isStopSymbol(ch)) {
- identBuf.append(buffer[pos]);
+ identBuf.append(ch);
pos++;
} else {
identifier = identBuf.toString();
diff --git a/luni/src/main/java/libcore/reflect/ListOfTypes.java b/luni/src/main/java/libcore/reflect/ListOfTypes.java
index c5d90e2..12ad84d 100644
--- a/luni/src/main/java/libcore/reflect/ListOfTypes.java
+++ b/luni/src/main/java/libcore/reflect/ListOfTypes.java
@@ -19,6 +19,7 @@
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
+import libcore.util.EmptyArray;
public final class ListOfTypes {
public static final ListOfTypes EMPTY = new ListOfTypes(0);
@@ -50,12 +51,20 @@
public Type[] getResolvedTypes() {
Type[] result = resolvedTypes;
- return result != null ? result : (resolvedTypes = resolveTypes(types));
+ if (result == null) {
+ result = resolveTypes(types);
+ resolvedTypes = result;
+ }
+ return result;
}
private Type[] resolveTypes(List<Type> unresolved) {
- Type[] result = new Type[unresolved.size()];
- for (int i = 0; i < unresolved.size(); i++) {
+ int size = unresolved.size();
+ if (size == 0) {
+ return EmptyArray.TYPE;
+ }
+ Type[] result = new Type[size];
+ for (int i = 0; i < size; i++) {
Type type = unresolved.get(i);
try {
result[i] = ((ParameterizedTypeImpl) type).getResolvedType();
diff --git a/luni/src/main/java/libcore/reflect/ListOfVariables.java b/luni/src/main/java/libcore/reflect/ListOfVariables.java
index 5d96817..43f2969 100644
--- a/luni/src/main/java/libcore/reflect/ListOfVariables.java
+++ b/luni/src/main/java/libcore/reflect/ListOfVariables.java
@@ -20,8 +20,6 @@
import java.util.ArrayList;
final class ListOfVariables {
- public static final TypeVariable[] EMPTY = new TypeVariableImpl[0];
-
final ArrayList<TypeVariable<?>> array = new ArrayList<TypeVariable<?>>();
void add (TypeVariable<?> elem) {
diff --git a/luni/src/main/java/libcore/reflect/Types.java b/luni/src/main/java/libcore/reflect/Types.java
index 2132b11..3181ca1 100644
--- a/luni/src/main/java/libcore/reflect/Types.java
+++ b/luni/src/main/java/libcore/reflect/Types.java
@@ -22,6 +22,7 @@
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;
+import libcore.util.EmptyArray;
public final class Types {
private Types() {
@@ -42,16 +43,19 @@
PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z");
}
- public static Type[] getClonedTypeArray(ListOfTypes types) {
- return types.getResolvedTypes().clone();
+ public static Type[] getTypeArray(ListOfTypes types, boolean clone) {
+ if (types.length() == 0) {
+ return EmptyArray.TYPE;
+ }
+ Type[] result = types.getResolvedTypes();
+ return clone ? result.clone() : result;
}
public static Type getType(Type type) {
if (type instanceof ParameterizedTypeImpl) {
return ((ParameterizedTypeImpl)type).getResolvedType();
- } else {
- return type;
}
+ return type;
}
/**
diff --git a/luni/src/main/java/libcore/util/EmptyArray.java b/luni/src/main/java/libcore/util/EmptyArray.java
index 6c99878..1713bfc 100644
--- a/luni/src/main/java/libcore/util/EmptyArray.java
+++ b/luni/src/main/java/libcore/util/EmptyArray.java
@@ -30,4 +30,7 @@
public static final String[] STRING = new String[0];
public static final Throwable[] THROWABLE = new Throwable[0];
public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0];
+ public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0];
+ public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE =
+ new java.lang.reflect.TypeVariable[0];
}
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
index 9d01f8d..c1d73df 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
@@ -30,6 +30,7 @@
import java.util.Map.Entry;
import java.util.Set;
import org.apache.harmony.security.asn1.ObjectIdentifier;
+import org.apache.harmony.security.fortress.Services;
/**
* Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
@@ -37,6 +38,9 @@
* providers during initialization.
*/
public class AlgNameMapper {
+ private static AlgNameMapperSource source = null;
+
+ private static volatile int cacheVersion = -1;
// Will search OID mappings for these services
private static final String[] serviceName = {
@@ -89,22 +93,29 @@
// map upper case alg name to its original name
algAliasesMap.put(algUC, element[1]);
}
- //
- // Now search providers for mappings like
- // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
- // or
- // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
- //
- Provider[] pl = Security.getProviders();
- for (Provider element : pl) {
- selectEntries(element);
- }
}
// No instances
private AlgNameMapper() {
}
+ private static synchronized void checkCacheVersion() {
+ int newCacheVersion = Services.getCacheVersion();
+ if (newCacheVersion != cacheVersion) {
+ //
+ // Now search providers for mappings like
+ // Alg.Alias.<service>.<OID-INTS-DOT-SEPARATED>=<alg-name>
+ // or
+ // Alg.Alias.<service>.OID.<OID-INTS-DOT-SEPARATED>=<alg-name>
+ //
+ Provider[] pl = Security.getProviders();
+ for (Provider element : pl) {
+ selectEntries(element);
+ }
+ cacheVersion = newCacheVersion;
+ }
+ }
+
/**
* Returns OID for algName
*
@@ -112,8 +123,21 @@
* @return OID as String
*/
public static String map2OID(String algName) {
+ checkCacheVersion();
+
// alg2OidMap map contains upper case keys
- return alg2OidMap.get(algName.toUpperCase(Locale.US));
+ String result = alg2OidMap.get(algName.toUpperCase(Locale.US));
+ if (result != null) {
+ return result;
+ }
+
+ // Check our external source.
+ AlgNameMapperSource s = source;
+ if (s != null) {
+ return s.mapNameToOid(algName);
+ }
+
+ return null;
}
/**
@@ -123,12 +147,21 @@
* @return algorithm name
*/
public static String map2AlgName(String oid) {
+ checkCacheVersion();
+
// oid2AlgMap map contains upper case values
- final String algUC = oid2AlgMap.get(oid);
+ String algUC = oid2AlgMap.get(oid);
// if not null there is always map UC->Orig
if (algUC != null) {
return algAliasesMap.get(algUC);
}
+
+ // Check our external source.
+ AlgNameMapperSource s = source;
+ if (s != null) {
+ return s.mapOidToName(oid);
+ }
+
return null;
}
@@ -204,4 +237,8 @@
? oid.substring(4)
: oid;
}
+
+ public static void setSource(AlgNameMapperSource source) {
+ AlgNameMapper.source = source;
+ }
}
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapperSource.java b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapperSource.java
new file mode 100644
index 0000000..abca36c
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapperSource.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 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 org.apache.harmony.security.utils;
+
+/**
+ * Provides a mapping source that the {@link AlgNameMapper} can query for
+ * mapping between algorithm names and OIDs.
+ */
+public interface AlgNameMapperSource {
+ public String mapNameToOid(String algName);
+
+ public String mapOidToName(String oid);
+}
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index ef9909b..c1bdd0f 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -32,13 +32,11 @@
return Locale::createFromName(ScopedUtfChars(env, localeName).c_str());
}
-jobjectArray fromStringEnumeration(JNIEnv* env, StringEnumeration* se) {
- UniquePtr<StringEnumeration> deleter(se);
- if (se == NULL) {
+jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, StringEnumeration* se) {
+ if (maybeThrowIcuException(env, provider, status)) {
return NULL;
}
- UErrorCode status = U_ZERO_ERROR;
int32_t count = se->count(status);
if (maybeThrowIcuException(env, "StringEnumeration::count", status)) {
return NULL;
diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h
index d93282c..cff1e0d 100644
--- a/luni/src/main/native/IcuUtilities.h
+++ b/luni/src/main/native/IcuUtilities.h
@@ -20,11 +20,12 @@
#define U_HAVE_STD_STRING 1 // For UnicodeString::toUTF8String(std::string&).
#include "jni.h"
+#include "ustrenum.h" // For UStringEnumeration.
#include "unicode/utypes.h" // For UErrorCode.
#include "unicode/locid.h" // For Locale.
extern Locale getLocale(JNIEnv* env, jstring localeName);
-extern jobjectArray fromStringEnumeration(JNIEnv* env, StringEnumeration*);
+extern jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, StringEnumeration*);
bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error);
#endif // ICU_UTILITIES_H_included
diff --git a/luni/src/main/native/JniException.cpp b/luni/src/main/native/JniException.cpp
index 8f97891..9744777 100644
--- a/luni/src/main/native/JniException.cpp
+++ b/luni/src/main/native/JniException.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <stdio.h> // For BUFSIZ
+
#include "JniException.h"
#include "JNIHelp.h"
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 54aecef..6b24a36 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear.
+#include "cutils/log.h"
#include "JniConstants.h"
#include "ScopedLocalFrame.h"
@@ -73,7 +74,6 @@
REGISTER(register_libcore_net_RawSocket);
REGISTER(register_org_apache_harmony_dalvik_NativeTestTarget);
REGISTER(register_org_apache_harmony_xml_ExpatParser);
- REGISTER(register_org_conscrypt_NativeCrypto);
REGISTER(register_sun_misc_Unsafe);
#undef REGISTER
return JNI_VERSION_1_6;
diff --git a/luni/src/main/native/ZipUtilities.cpp b/luni/src/main/native/ZipUtilities.cpp
new file mode 100644
index 0000000..745b3b1
--- /dev/null
+++ b/luni/src/main/native/ZipUtilities.cpp
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+#include "JniConstants.h"
+#include "JniException.h"
+#include "UniquePtr.h"
+#include "ZipUtilities.h"
+
+void throwExceptionForZlibError(JNIEnv* env, const char* exceptionClassName, int error,
+ NativeZipStream* stream) {
+ if (error == Z_MEM_ERROR) {
+ jniThrowOutOfMemoryError(env, NULL);
+ } else if (stream != NULL && stream->stream.msg != NULL) {
+ jniThrowException(env, exceptionClassName, stream->stream.msg);
+ } else {
+ jniThrowException(env, exceptionClassName, zError(error));
+ }
+}
+
+NativeZipStream::NativeZipStream() : input(NULL), inCap(0), mDict(NULL) {
+ // Let zlib use its default allocator.
+ stream.opaque = Z_NULL;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+}
+
+NativeZipStream::~NativeZipStream() {
+}
+
+void NativeZipStream::setDictionary(JNIEnv* env, jbyteArray javaDictionary, int off, int len,
+ bool inflate) {
+ UniquePtr<jbyte[]> dictionaryBytes(new jbyte[len]);
+ if (dictionaryBytes.get() == NULL) {
+ jniThrowOutOfMemoryError(env, NULL);
+ return;
+ }
+ env->GetByteArrayRegion(javaDictionary, off, len, &dictionaryBytes[0]);
+ const Bytef* dictionary = reinterpret_cast<const Bytef*>(&dictionaryBytes[0]);
+ int err;
+ if (inflate) {
+ err = inflateSetDictionary(&stream, dictionary, len);
+ } else {
+ err = deflateSetDictionary(&stream, dictionary, len);
+ }
+ if (err != Z_OK) {
+ throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err, NULL);
+ return;
+ }
+ mDict.reset(dictionaryBytes.release());
+}
+
+void NativeZipStream::setInput(JNIEnv* env, jbyteArray buf, jint off, jint len) {
+ input.reset(new jbyte[len]);
+ if (input.get() == NULL) {
+ inCap = 0;
+ jniThrowOutOfMemoryError(env, NULL);
+ return;
+ }
+ inCap = len;
+ if (buf != NULL) {
+ env->GetByteArrayRegion(buf, off, len, &input[0]);
+ }
+ stream.next_in = reinterpret_cast<Bytef*>(&input[0]);
+ stream.avail_in = len;
+}
+
+NativeZipStream* toNativeZipStream(jlong address) {
+ return reinterpret_cast<NativeZipStream*>(static_cast<uintptr_t>(address));
+}
diff --git a/luni/src/main/native/ZipUtilities.h b/luni/src/main/native/ZipUtilities.h
index 4c86f32..fe0f977 100644
--- a/luni/src/main/native/ZipUtilities.h
+++ b/luni/src/main/native/ZipUtilities.h
@@ -18,20 +18,9 @@
#ifndef ZIP_UTILITIES_H_included
#define ZIP_UTILITIES_H_included
-#include "JNIHelp.h"
-#include "JniException.h"
#include "UniquePtr.h"
#include "jni.h"
#include "zlib.h"
-#include "zutil.h" // For DEF_WBITS and DEF_MEM_LEVEL.
-
-static void throwExceptionForZlibError(JNIEnv* env, const char* exceptionClassName, int error) {
- if (error == Z_MEM_ERROR) {
- jniThrowOutOfMemoryError(env, NULL);
- } else {
- jniThrowException(env, exceptionClassName, zError(error));
- }
-}
class NativeZipStream {
public:
@@ -39,51 +28,10 @@
int inCap;
z_stream stream;
- NativeZipStream() : input(NULL), inCap(0), mDict(NULL) {
- // Let zlib use its default allocator.
- stream.opaque = Z_NULL;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- }
-
- ~NativeZipStream() {
- }
-
- void setDictionary(JNIEnv* env, jbyteArray javaDictionary, int off, int len, bool inflate) {
- UniquePtr<jbyte[]> dictionaryBytes(new jbyte[len]);
- if (dictionaryBytes.get() == NULL) {
- jniThrowOutOfMemoryError(env, NULL);
- return;
- }
- env->GetByteArrayRegion(javaDictionary, off, len, &dictionaryBytes[0]);
- const Bytef* dictionary = reinterpret_cast<const Bytef*>(&dictionaryBytes[0]);
- int err;
- if (inflate) {
- err = inflateSetDictionary(&stream, dictionary, len);
- } else {
- err = deflateSetDictionary(&stream, dictionary, len);
- }
- if (err != Z_OK) {
- throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err);
- return;
- }
- mDict.reset(dictionaryBytes.release());
- }
-
- void setInput(JNIEnv* env, jbyteArray buf, jint off, jint len) {
- input.reset(new jbyte[len]);
- if (input.get() == NULL) {
- inCap = 0;
- jniThrowOutOfMemoryError(env, NULL);
- return;
- }
- inCap = len;
- if (buf != NULL) {
- env->GetByteArrayRegion(buf, off, len, &input[0]);
- }
- stream.next_in = reinterpret_cast<Bytef*>(&input[0]);
- stream.avail_in = len;
- }
+ NativeZipStream();
+ ~NativeZipStream();
+ void setDictionary(JNIEnv* env, jbyteArray javaDictionary, int off, int len, bool inflate);
+ void setInput(JNIEnv* env, jbyteArray buf, jint off, jint len);
private:
UniquePtr<jbyte[]> mDict;
@@ -93,8 +41,9 @@
void operator=(const NativeZipStream&);
};
-static NativeZipStream* toNativeZipStream(jlong address) {
- return reinterpret_cast<NativeZipStream*>(static_cast<uintptr_t>(address));
-}
+NativeZipStream* toNativeZipStream(jlong address);
+
+void throwExceptionForZlibError(JNIEnv* env, const char* exceptionClassName, int error,
+ NativeZipStream* stream);
#endif // ZIP_UTILITIES_H_included
diff --git a/luni/src/main/native/java_lang_Character.cpp b/luni/src/main/native/java_lang_Character.cpp
index de1800e..14eef64 100644
--- a/luni/src/main/native/java_lang_Character.cpp
+++ b/luni/src/main/native/java_lang_Character.cpp
@@ -21,6 +21,7 @@
#include "ScopedUtfChars.h"
#include "unicode/uchar.h"
#include <math.h>
+#include <stdio.h> // For BUFSIZ
#include <stdlib.h>
static jint Character_digitImpl(JNIEnv*, jclass, jint codePoint, jint radix) {
diff --git a/luni/src/main/native/java_util_zip_Deflater.cpp b/luni/src/main/native/java_util_zip_Deflater.cpp
index ed7d754..1afd36e 100644
--- a/luni/src/main/native/java_util_zip_Deflater.cpp
+++ b/luni/src/main/native/java_util_zip_Deflater.cpp
@@ -18,8 +18,10 @@
#define LOG_TAG "Deflater"
#include "JniConstants.h"
+#include "JniException.h"
#include "ScopedPrimitiveArray.h"
#include "ZipUtilities.h"
+#include "zutil.h" // For DEF_WBITS and DEF_MEM_LEVEL.
static void Deflater_setDictionaryImpl(JNIEnv* env, jobject, jbyteArray dict, int off, int len, jlong handle) {
toNativeZipStream(handle)->setDictionary(env, dict, off, len, false);
@@ -56,7 +58,7 @@
int memLevel = DEF_MEM_LEVEL;
int err = deflateInit2(&jstream->stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
if (err != Z_OK) {
- throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err);
+ throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err, jstream.get());
return -1;
}
return reinterpret_cast<uintptr_t>(jstream.release());
@@ -92,7 +94,7 @@
// input and more output space to continue compressing".
break;
default:
- throwExceptionForZlibError(env, "java/util/zip/DataFormatException", err);
+ throwExceptionForZlibError(env, "java/util/zip/DataFormatException", err, stream);
return -1;
}
@@ -116,7 +118,7 @@
NativeZipStream* stream = toNativeZipStream(handle);
int err = deflateReset(&stream->stream);
if (err != Z_OK) {
- throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err);
+ throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err, stream);
}
}
@@ -130,7 +132,7 @@
stream->stream.avail_out = 0;
int err = deflateParams(&stream->stream, level, strategy);
if (err != Z_OK) {
- throwExceptionForZlibError(env, "java/lang/IllegalStateException", err);
+ throwExceptionForZlibError(env, "java/lang/IllegalStateException", err, stream);
}
}
diff --git a/luni/src/main/native/java_util_zip_Inflater.cpp b/luni/src/main/native/java_util_zip_Inflater.cpp
index 6aa3e24..ca3ee09 100644
--- a/luni/src/main/native/java_util_zip_Inflater.cpp
+++ b/luni/src/main/native/java_util_zip_Inflater.cpp
@@ -18,8 +18,10 @@
#define LOG_TAG "Inflater"
#include "JniConstants.h"
+#include "JniException.h"
#include "ScopedPrimitiveArray.h"
#include "ZipUtilities.h"
+#include "zutil.h" // For DEF_WBITS and DEF_MEM_LEVEL.
#include <errno.h>
static jlong Inflater_createStream(JNIEnv* env, jobject, jboolean noHeader) {
@@ -40,7 +42,7 @@
*/
int err = inflateInit2(&jstream->stream, noHeader ? -DEF_WBITS : DEF_WBITS);
if (err != Z_OK) {
- throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err);
+ throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err, jstream.get());
return -1;
}
return reinterpret_cast<uintptr_t>(jstream.release());
@@ -113,7 +115,7 @@
case Z_STREAM_ERROR:
return 0;
default:
- throwExceptionForZlibError(env, "java/util/zip/DataFormatException", err);
+ throwExceptionForZlibError(env, "java/util/zip/DataFormatException", err, stream);
return -1;
}
@@ -142,9 +144,10 @@
}
static void Inflater_resetImpl(JNIEnv* env, jobject, jlong handle) {
- int err = inflateReset(&toNativeZipStream(handle)->stream);
+ NativeZipStream* stream = toNativeZipStream(handle);
+ int err = inflateReset(&stream->stream);
if (err != Z_OK) {
- throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err);
+ throwExceptionForZlibError(env, "java/lang/IllegalArgumentException", err, stream);
}
}
diff --git a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
index 65ace4e..72bc631 100644
--- a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
@@ -23,41 +23,52 @@
#include "cutils/log.h"
#include "unicode/dtitvfmt.h"
-static jstring DateIntervalFormat_formatDateInterval(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName, jstring javaTzName, jlong fromDate, jlong toDate) {
+static jlong DateIntervalFormat_createDateIntervalFormat(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName, jstring javaTzName) {
Locale locale = getLocale(env, javaLocaleName);
ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton);
if (!skeletonHolder.valid()) {
- return NULL;
+ return 0;
+ }
+
+ UErrorCode status = U_ZERO_ERROR;
+ DateIntervalFormat* formatter(DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), locale, status));
+ if (maybeThrowIcuException(env, "DateIntervalFormat::createInstance", status)) {
+ return 0;
}
ScopedJavaUnicodeString tzNameHolder(env, javaTzName);
if (!tzNameHolder.valid()) {
- return NULL;
+ return 0;
}
-
- UErrorCode status = U_ZERO_ERROR;
- UniquePtr<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), locale, status));
- if (maybeThrowIcuException(env, "DateIntervalFormat::createInstance", status)) {
- return NULL;
- }
-
formatter->adoptTimeZone(TimeZone::createTimeZone(tzNameHolder.unicodeString()));
+ return reinterpret_cast<uintptr_t>(formatter);
+}
+
+static void DateIntervalFormat_destroyDateIntervalFormat(JNIEnv*, jclass, jlong address) {
+ delete reinterpret_cast<DateIntervalFormat*>(address);
+}
+
+static jstring DateIntervalFormat_formatDateInterval(JNIEnv* env, jclass, jlong address, jlong fromDate, jlong toDate) {
+ DateIntervalFormat* formatter(reinterpret_cast<DateIntervalFormat*>(address));
DateInterval date_interval(fromDate, toDate);
- UnicodeString result;
+ UnicodeString s;
FieldPosition pos = 0;
- formatter->format(&date_interval, result, pos, status);
+ UErrorCode status = U_ZERO_ERROR;
+ formatter->format(&date_interval, s, pos, status);
if (maybeThrowIcuException(env, "DateIntervalFormat::format", status)) {
- return NULL;
+ return NULL;
}
- return env->NewString(result.getBuffer(), result.length());
+ return env->NewString(s.getBuffer(), s.length());
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(DateIntervalFormat, formatDateInterval, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJ)Ljava/lang/String;"),
+ NATIVE_METHOD(DateIntervalFormat, createDateIntervalFormat, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J"),
+ NATIVE_METHOD(DateIntervalFormat, destroyDateIntervalFormat, "(J)V"),
+ NATIVE_METHOD(DateIntervalFormat, formatDateInterval, "(JJJ)Ljava/lang/String;"),
};
void register_libcore_icu_DateIntervalFormat(JNIEnv* env) {
jniRegisterNativeMethods(env, "libcore/icu/DateIntervalFormat", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index 40d6e04..5bbb506 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -439,28 +439,6 @@
return true;
}
-static bool getTimeFormats12And24(JNIEnv* env, jobject localeData, Locale& locale) {
- UErrorCode status = U_ZERO_ERROR;
- DateTimePatternGenerator* generator = DateTimePatternGenerator::createInstance(locale, status);
- if (U_FAILURE(status)) {
- return false;
- }
-
- UnicodeString pattern_Hm(generator->getBestPattern(UnicodeString("Hm", 2, US_INV), status));
- if (U_FAILURE(status)) {
- return false;
- }
-
- UnicodeString pattern_hm(generator->getBestPattern(UnicodeString("hm", 2, US_INV), status));
- if (U_FAILURE(status)) {
- return false;
- }
-
- setStringField(env, localeData, "timeFormat12", pattern_hm);
- setStringField(env, localeData, "timeFormat24", pattern_Hm);
- return true;
-}
-
static bool getYesterdayTodayAndTomorrow(JNIEnv* env, jobject localeData, const char* locale_name) {
UErrorCode status = U_ZERO_ERROR;
ScopedResourceBundle root(ures_open(NULL, locale_name, &status));
@@ -489,7 +467,7 @@
return false;
}
-static jboolean ICU_initLocaleDataImpl(JNIEnv* env, jclass, jstring javaLocaleName, jobject localeData) {
+static jboolean ICU_initLocaleDataNative(JNIEnv* env, jclass, jstring javaLocaleName, jobject localeData) {
ScopedUtfChars localeName(env, javaLocaleName);
if (localeName.c_str() == NULL) {
return JNI_FALSE;
@@ -512,13 +490,6 @@
return JNI_FALSE;
}
- // Get the "h:mm a" and "HH:mm" 12- and 24-hour time format strings.
- Locale locale = getLocale(env, javaLocaleName);
- if (!getTimeFormats12And24(env, localeData, locale)) {
- ALOGE("Couldn't find ICU 12- and 24-hour time formats for %s", localeName.c_str());
- return JNI_FALSE;
- }
-
// Get the "Yesterday", "Today", and "Tomorrow" strings.
bool foundYesterdayTodayAndTomorrow = false;
for (LocaleNameIterator it(localeName.c_str(), status); it.HasNext(); it.Up()) {
@@ -533,6 +504,7 @@
}
status = U_ZERO_ERROR;
+ Locale locale = getLocale(env, javaLocaleName);
UniquePtr<Calendar> cal(Calendar::createInstance(locale, status));
if (U_FAILURE(status)) {
return JNI_FALSE;
@@ -667,35 +639,16 @@
return versionString(env, unicodeVersion);
}
-struct EnumerationCounter {
- const size_t count;
- EnumerationCounter(size_t count) : count(count) {}
- size_t operator()() { return count; }
-};
-struct EnumerationGetter {
- UEnumeration* e;
- UErrorCode* status;
- EnumerationGetter(UEnumeration* e, UErrorCode* status) : e(e), status(status) {}
- const UChar* operator()(int32_t* charCount) { return uenum_unext(e, charCount, status); }
-};
static jobject ICU_getAvailableCurrencyCodes(JNIEnv* env, jclass) {
- UErrorCode status = U_ZERO_ERROR;
- UEnumeration* e(ucurr_openISOCurrencies(UCURR_COMMON|UCURR_NON_DEPRECATED, &status));
- EnumerationCounter counter(uenum_count(e, &status));
- if (maybeThrowIcuException(env, "uenum_count", status)) {
- return NULL;
- }
- EnumerationGetter getter(e, &status);
- jobject result = toStringArray16(env, &counter, &getter);
- maybeThrowIcuException(env, "uenum_unext", status);
- uenum_close(e);
- return result;
+ UErrorCode status = U_ZERO_ERROR;
+ UStringEnumeration e(ucurr_openISOCurrencies(UCURR_COMMON|UCURR_NON_DEPRECATED, &status));
+ return fromStringEnumeration(env, status, "ucurr_openISOCurrencies", &e);
}
-static jstring ICU_getBestDateTimePattern(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName) {
+static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName) {
Locale locale = getLocale(env, javaLocaleName);
UErrorCode status = U_ZERO_ERROR;
- DateTimePatternGenerator* generator = DateTimePatternGenerator::createInstance(locale, status);
+ UniquePtr<DateTimePatternGenerator> generator(DateTimePatternGenerator::createInstance(locale, status));
if (maybeThrowIcuException(env, "DateTimePatternGenerator::createInstance", status)) {
return NULL;
}
@@ -721,7 +674,7 @@
NATIVE_METHOD(ICU, getAvailableDateFormatLocalesNative, "()[Ljava/lang/String;"),
NATIVE_METHOD(ICU, getAvailableLocalesNative, "()[Ljava/lang/String;"),
NATIVE_METHOD(ICU, getAvailableNumberFormatLocalesNative, "()[Ljava/lang/String;"),
- NATIVE_METHOD(ICU, getBestDateTimePattern, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
+ NATIVE_METHOD(ICU, getBestDateTimePatternNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ICU, getCldrVersion, "()Ljava/lang/String;"),
NATIVE_METHOD(ICU, getCurrencyCode, "(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ICU, getCurrencyDisplayName, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
@@ -737,7 +690,7 @@
NATIVE_METHOD(ICU, getIcuVersion, "()Ljava/lang/String;"),
NATIVE_METHOD(ICU, getScript, "(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ICU, getUnicodeVersion, "()Ljava/lang/String;"),
- NATIVE_METHOD(ICU, initLocaleDataImpl, "(Ljava/lang/String;Llibcore/icu/LocaleData;)Z"),
+ NATIVE_METHOD(ICU, initLocaleDataNative, "(Ljava/lang/String;Llibcore/icu/LocaleData;)Z"),
NATIVE_METHOD(ICU, toLowerCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ICU, toUpperCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
};
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index fae56b7..137e172 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -57,17 +57,105 @@
UConverterFromUCallback onMalformedInput;
};
-struct UConverterDeleter {
- void operator()(UConverter* p) const {
- ucnv_close(p);
- }
-};
-typedef UniquePtr<UConverter, UConverterDeleter> UniqueUConverter;
-
static UConverter* toUConverter(jlong address) {
return reinterpret_cast<UConverter*>(static_cast<uintptr_t>(address));
}
+static bool collectStandardNames(JNIEnv* env, const char* canonicalName, const char* standard,
+ std::vector<std::string>& result) {
+ UErrorCode status = U_ZERO_ERROR;
+ UStringEnumeration e(ucnv_openStandardNames(canonicalName, standard, &status));
+ if (maybeThrowIcuException(env, "ucnv_openStandardNames", status)) {
+ return false;
+ }
+
+ int32_t count = e.count(status);
+ if (maybeThrowIcuException(env, "StringEnumeration::count", status)) {
+ return false;
+ }
+
+ for (int32_t i = 0; i < count; ++i) {
+ const UnicodeString* string = e.snext(status);
+ if (maybeThrowIcuException(env, "StringEnumeration::snext", status)) {
+ return false;
+ }
+ std::string s;
+ string->toUTF8String(s);
+ if (s.find_first_of("+,") == std::string::npos) {
+ result.push_back(s);
+ }
+ }
+
+ return true;
+}
+
+static const char* getICUCanonicalName(const char* name) {
+ UErrorCode error = U_ZERO_ERROR;
+ const char* canonicalName = NULL;
+ if ((canonicalName = ucnv_getCanonicalName(name, "MIME", &error)) != NULL) {
+ return canonicalName;
+ } else if ((canonicalName = ucnv_getCanonicalName(name, "IANA", &error)) != NULL) {
+ return canonicalName;
+ } else if ((canonicalName = ucnv_getCanonicalName(name, "", &error)) != NULL) {
+ return canonicalName;
+ } else if ((canonicalName = ucnv_getAlias(name, 0, &error)) != NULL) {
+ // We have some aliases in the form x-blah .. match those first.
+ return canonicalName;
+ } else if (strstr(name, "x-") == name) {
+ // Check if the converter can be opened with the name given.
+ error = U_ZERO_ERROR;
+ LocalUConverterPointer cnv(ucnv_open(name + 2, &error));
+ if (U_SUCCESS(error)) {
+ return name + 2;
+ }
+ }
+ return NULL;
+}
+
+// If a charset listed in the IANA Charset Registry is supported by an implementation
+// of the Java platform then its canonical name must be the name listed in the registry.
+// Many charsets are given more than one name in the registry, in which case the registry
+// identifies one of the names as MIME-preferred. If a charset has more than one registry
+// name then its canonical name must be the MIME-preferred name and the other names in
+// the registry must be valid aliases. If a supported charset is not listed in the IANA
+// registry then its canonical name must begin with one of the strings "X-" or "x-".
+static jstring getJavaCanonicalName(JNIEnv* env, const char* icuCanonicalName) {
+ UErrorCode status = U_ZERO_ERROR;
+
+ // Check to see if this is a well-known MIME or IANA name.
+ const char* cName = NULL;
+ if ((cName = ucnv_getStandardName(icuCanonicalName, "MIME", &status)) != NULL) {
+ return env->NewStringUTF(cName);
+ } else if ((cName = ucnv_getStandardName(icuCanonicalName, "IANA", &status)) != NULL) {
+ return env->NewStringUTF(cName);
+ }
+
+ // Check to see if an alias already exists with "x-" prefix, if yes then
+ // make that the canonical name.
+ int32_t aliasCount = ucnv_countAliases(icuCanonicalName, &status);
+ for (int i = 0; i < aliasCount; ++i) {
+ const char* name = ucnv_getAlias(icuCanonicalName, i, &status);
+ if (name != NULL && name[0] == 'x' && name[1] == '-') {
+ return env->NewStringUTF(name);
+ }
+ }
+
+ // As a last resort, prepend "x-" to any alias and make that the canonical name.
+ status = U_ZERO_ERROR;
+ const char* name = ucnv_getStandardName(icuCanonicalName, "UTR22", &status);
+ if (name == NULL && strchr(icuCanonicalName, ',') != NULL) {
+ name = ucnv_getAlias(icuCanonicalName, 1, &status);
+ }
+ // If there is no UTR22 canonical name then just return the original name.
+ if (name == NULL) {
+ name = icuCanonicalName;
+ }
+ UniquePtr<char[]> result(new char[2 + strlen(name) + 1]);
+ strcpy(&result[0], "x-");
+ strcat(&result[0], name);
+ return env->NewStringUTF(&result[0]);
+}
+
static jlong NativeConverter_openConverter(JNIEnv* env, jclass, jstring converterName) {
ScopedUtfChars converterNameChars(env, converterName);
if (converterNameChars.c_str() == NULL) {
@@ -230,52 +318,6 @@
return (cnv != NULL) ? ((ucnv_getMaxCharSize(cnv) + ucnv_getMinCharSize(cnv)) / 2.0) : -1;
}
-/*
- * If a charset listed in the IANA Charset Registry is supported by an implementation
- * of the Java platform then its canonical name must be the name listed in the registry.
- * Many charsets are given more than one name in the registry, in which case the registry
- * identifies one of the names as MIME-preferred. If a charset has more than one registry
- * name then its canonical name must be the MIME-preferred name and the other names in
- * the registry must be valid aliases. If a supported charset is not listed in the IANA
- * registry then its canonical name must begin with one of the strings "X-" or "x-".
- */
-static jstring getJavaCanonicalName(JNIEnv* env, const char* icuCanonicalName) {
- UErrorCode status = U_ZERO_ERROR;
-
- // Check to see if this is a well-known MIME or IANA name.
- const char* cName = NULL;
- if ((cName = ucnv_getStandardName(icuCanonicalName, "MIME", &status)) != NULL) {
- return env->NewStringUTF(cName);
- } else if ((cName = ucnv_getStandardName(icuCanonicalName, "IANA", &status)) != NULL) {
- return env->NewStringUTF(cName);
- }
-
- // Check to see if an alias already exists with "x-" prefix, if yes then
- // make that the canonical name.
- int32_t aliasCount = ucnv_countAliases(icuCanonicalName, &status);
- for (int i = 0; i < aliasCount; ++i) {
- const char* name = ucnv_getAlias(icuCanonicalName, i, &status);
- if (name != NULL && name[0] == 'x' && name[1] == '-') {
- return env->NewStringUTF(name);
- }
- }
-
- // As a last resort, prepend "x-" to any alias and make that the canonical name.
- status = U_ZERO_ERROR;
- const char* name = ucnv_getStandardName(icuCanonicalName, "UTR22", &status);
- if (name == NULL && strchr(icuCanonicalName, ',') != NULL) {
- name = ucnv_getAlias(icuCanonicalName, 1, &status);
- }
- // If there is no UTR22 canonical name then just return the original name.
- if (name == NULL) {
- name = icuCanonicalName;
- }
- UniquePtr<char[]> result(new char[2 + strlen(name) + 1]);
- strcpy(&result[0], "x-");
- strcat(&result[0], name);
- return env->NewStringUTF(&result[0]);
-}
-
static jobjectArray NativeConverter_getAvailableCharsetNames(JNIEnv* env, jclass) {
int32_t num = ucnv_countAvailable();
jobjectArray result = env->NewObjectArray(num, JniConstants::stringClass, NULL);
@@ -296,57 +338,6 @@
return result;
}
-static jobjectArray getAliases(JNIEnv* env, const char* icuCanonicalName) {
- // Get an upper bound on the number of aliases...
- const char* myEncName = icuCanonicalName;
- UErrorCode error = U_ZERO_ERROR;
- size_t aliasCount = ucnv_countAliases(myEncName, &error);
- if (aliasCount == 0 && myEncName[0] == 'x' && myEncName[1] == '-') {
- myEncName = myEncName + 2;
- aliasCount = ucnv_countAliases(myEncName, &error);
- }
- if (!U_SUCCESS(error)) {
- return NULL;
- }
-
- // Collect the aliases we want...
- std::vector<std::string> aliases;
- for (size_t i = 0; i < aliasCount; ++i) {
- const char* name = ucnv_getAlias(myEncName, i, &error);
- if (!U_SUCCESS(error)) {
- return NULL;
- }
- // TODO: why do we ignore these ones?
- if (strchr(name, '+') == 0 && strchr(name, ',') == 0) {
- aliases.push_back(name);
- }
- }
- return toStringArray(env, aliases);
-}
-
-static const char* getICUCanonicalName(const char* name) {
- UErrorCode error = U_ZERO_ERROR;
- const char* canonicalName = NULL;
- if ((canonicalName = ucnv_getCanonicalName(name, "MIME", &error)) != NULL) {
- return canonicalName;
- } else if((canonicalName = ucnv_getCanonicalName(name, "IANA", &error)) != NULL) {
- return canonicalName;
- } else if((canonicalName = ucnv_getCanonicalName(name, "", &error)) != NULL) {
- return canonicalName;
- } else if((canonicalName = ucnv_getAlias(name, 0, &error)) != NULL) {
- /* we have some aliases in the form x-blah .. match those first */
- return canonicalName;
- } else if (strstr(name, "x-") == name) {
- /* check if the converter can be opened with the name given */
- error = U_ZERO_ERROR;
- UniqueUConverter cnv(ucnv_open(name + 2, &error));
- if (cnv.get() != NULL) {
- return name + 2;
- }
- }
- return NULL;
-}
-
static void CHARSET_ENCODER_CALLBACK(const void* rawContext, UConverterFromUnicodeArgs* args,
const UChar* codeUnits, int32_t length, UChar32 codePoint, UConverterCallbackReason reason,
UErrorCode* status) {
@@ -544,13 +535,13 @@
}
UErrorCode errorCode = U_ZERO_ERROR;
- UniqueUConverter converter1(ucnv_open(name1Chars.c_str(), &errorCode));
+ LocalUConverterPointer converter1(ucnv_open(name1Chars.c_str(), &errorCode));
UnicodeSet set1;
- ucnv_getUnicodeSet(converter1.get(), set1.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode);
+ ucnv_getUnicodeSet(&*converter1, set1.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode);
- UniqueUConverter converter2(ucnv_open(name2Chars.c_str(), &errorCode));
+ LocalUConverterPointer converter2(ucnv_open(name2Chars.c_str(), &errorCode));
UnicodeSet set2;
- ucnv_getUnicodeSet(converter2.get(), set2.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode);
+ ucnv_getUnicodeSet(&*converter2, set2.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode);
return U_SUCCESS(errorCode) && set1.containsAll(set2);
}
@@ -560,11 +551,13 @@
if (charsetNameChars.c_str() == NULL) {
return NULL;
}
+
// Get ICU's canonical name for this charset.
const char* icuCanonicalName = getICUCanonicalName(charsetNameChars.c_str());
if (icuCanonicalName == NULL) {
return NULL;
}
+
// Get Java's canonical name for this charset.
jstring javaCanonicalName = getJavaCanonicalName(env, icuCanonicalName);
if (env->ExceptionCheck()) {
@@ -572,17 +565,30 @@
}
// Check that this charset is supported.
- // ICU doesn't offer any "isSupported", so we just open and immediately close.
- // We ignore the UErrorCode because ucnv_open returning NULL is all the information we need.
- UErrorCode dummy = U_ZERO_ERROR;
- UniqueUConverter cnv(ucnv_open(icuCanonicalName, &dummy));
- if (cnv.get() == NULL) {
- return NULL;
+ {
+ // ICU doesn't offer any "isSupported", so we just open and immediately close.
+ UErrorCode error = U_ZERO_ERROR;
+ LocalUConverterPointer cnv(ucnv_open(icuCanonicalName, &error));
+ if (!U_SUCCESS(error)) {
+ return NULL;
+ }
}
- cnv.reset();
// Get the aliases for this charset.
- jobjectArray aliases = getAliases(env, icuCanonicalName);
+ std::vector<std::string> aliases;
+ if (!collectStandardNames(env, icuCanonicalName, "IANA", aliases)) {
+ return NULL;
+ }
+ if (!collectStandardNames(env, icuCanonicalName, "MIME", aliases)) {
+ return NULL;
+ }
+ if (!collectStandardNames(env, icuCanonicalName, "JAVA", aliases)) {
+ return NULL;
+ }
+ if (!collectStandardNames(env, icuCanonicalName, "WINDOWS", aliases)) {
+ return NULL;
+ }
+ jobjectArray javaAliases = toStringArray(env, aliases);
if (env->ExceptionCheck()) {
return NULL;
}
@@ -594,7 +600,7 @@
return NULL;
}
return env->NewObject(JniConstants::charsetICUClass, charsetConstructor,
- javaCanonicalName, env->NewStringUTF(icuCanonicalName), aliases);
+ javaCanonicalName, env->NewStringUTF(icuCanonicalName), javaAliases);
}
static JNINativeMethod gMethods[] = {
diff --git a/luni/src/main/native/libcore_icu_Transliterator.cpp b/luni/src/main/native/libcore_icu_Transliterator.cpp
index f2a54cb..0c52053 100644
--- a/luni/src/main/native/libcore_icu_Transliterator.cpp
+++ b/luni/src/main/native/libcore_icu_Transliterator.cpp
@@ -46,7 +46,8 @@
static jobjectArray Transliterator_getAvailableIDs(JNIEnv* env, jclass) {
UErrorCode status = U_ZERO_ERROR;
- return fromStringEnumeration(env, Transliterator::getAvailableIDs(status));
+ StringEnumeration* e = Transliterator::getAvailableIDs(status);
+ return fromStringEnumeration(env, status, "Transliterator::getAvailableIDs", e);
}
static jstring Transliterator_transliterate(JNIEnv* env, jclass, jlong peer, jstring javaString) {
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 7093a68..cf1b714 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "Posix"
#include "AsynchronousSocketCloseMonitor.h"
+#include "cutils/log.h"
#include "ExecStrings.h"
#include "JNIHelp.h"
#include "JniConstants.h"
diff --git a/luni/src/main/native/libcore_net_RawSocket.cpp b/luni/src/main/native/libcore_net_RawSocket.cpp
index 2e493ac..f8a8506 100644
--- a/luni/src/main/native/libcore_net_RawSocket.cpp
+++ b/luni/src/main/native/libcore_net_RawSocket.cpp
@@ -14,7 +14,10 @@
* limitations under the License.
*/
+#define LOG_TAG "RawSocket"
+
#include "AsynchronousSocketCloseMonitor.h"
+#include "cutils/log.h"
#include "JNIHelp.h"
#include "JniException.h"
#include "JniConstants.h"
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index e576d1a..8a1d7c5 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -10,6 +10,7 @@
JniException.cpp \
NetworkUtilities.cpp \
Register.cpp \
+ ZipUtilities.cpp \
cbigint.cpp \
java_io_Console.cpp \
java_io_File.cpp \
diff --git a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
index 899bd46..801db4b 100644
--- a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
+++ b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
@@ -51,6 +51,8 @@
// Kanji (sorts to inflow section)
assertHasLabel(ja, "\u65e5", "");
+ // http://bugs.icu-project.org/trac/ticket/10423 / http://b/10809397
+ assertHasLabel(ja, "\u95c7", "");
// English
assertHasLabel(ja, "Smith", "S");
diff --git a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
index 8de3407..c8cf572 100644
--- a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
+++ b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
@@ -26,39 +26,45 @@
import static libcore.icu.DateIntervalFormat.*;
public class DateIntervalFormatTest extends junit.framework.TestCase {
- private static final long MINUTE_DURATION = 60 * 1000;
- private static final long HOUR_DURATION = 60 * MINUTE_DURATION;
- private static final long DAY_DURATION = 24 * HOUR_DURATION;
- private static final long MONTH_DURATION = 31 * DAY_DURATION;
- private static final long YEAR_DURATION = 12 * MONTH_DURATION;
+ private static final long MINUTE = 60 * 1000;
+ private static final long HOUR = 60 * MINUTE;
+ private static final long DAY = 24 * HOUR;
+ private static final long MONTH = 31 * DAY;
+ private static final long YEAR = 12 * MONTH;
+ // These are the old CTS tests for DateIntervalFormat.formatDateRange.
public void test_formatDateInterval() throws Exception {
- Date date = new Date(109, 0, 19, 3, 30, 15);
- long fixedTime = date.getTime();
+ TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
- int currentYear = Calendar.getInstance().get(Calendar.YEAR);
- Date dateWithCurrentYear = new Date(currentYear - 1900, 0, 19, 3, 30, 15);
- long timeWithCurrentYear = dateWithCurrentYear.getTime();
+ Calendar c = Calendar.getInstance(tz, Locale.US);
+ c.set(Calendar.MONTH, Calendar.JANUARY);
+ c.set(Calendar.DAY_OF_MONTH, 19);
+ c.set(Calendar.HOUR_OF_DAY, 3);
+ c.set(Calendar.MINUTE, 30);
+ c.set(Calendar.SECOND, 15);
+ long timeWithCurrentYear = c.getTimeInMillis();
+
+ c.set(Calendar.YEAR, 2009);
+ long fixedTime = c.getTimeInMillis();
+
+ c.set(Calendar.MINUTE, 0);
+ c.set(Calendar.SECOND, 0);
+ long onTheHour = c.getTimeInMillis();
long noonDuration = (8 * 60 + 30) * 60 * 1000 - 15 * 1000;
long midnightDuration = (3 * 60 + 30) * 60 * 1000 + 15 * 1000;
- long integralDuration = 30 * 60 * 1000 + 15 * 1000;
-
- // These are the old CTS tests for DateIntervalFormat.formatDateRange.
Locale de_DE = new Locale("de", "DE");
Locale en_US = new Locale("en", "US");
Locale es_ES = new Locale("es", "ES");
Locale es_US = new Locale("es", "US");
- TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
-
- assertEquals("Monday", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_WEEKDAY));
- assertEquals("January 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_SHOW_DATE));
+ assertEquals("Monday", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_WEEKDAY));
+ assertEquals("January 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, FORMAT_SHOW_DATE));
assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_SHOW_TIME));
- assertEquals("January 19, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR));
- assertEquals("January 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, 0 /*FORMAT_NO_YEAR*/));
- assertEquals("January", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_NO_MONTH_DAY));
+ assertEquals("January 19, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_YEAR));
+ assertEquals("January 19", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_NO_YEAR));
+ assertEquals("January", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, FORMAT_NO_MONTH_DAY));
assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_12HOUR | FORMAT_SHOW_TIME));
assertEquals("03:30", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_24HOUR | FORMAT_SHOW_TIME));
assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_12HOUR /*| FORMAT_CAP_AMPM*/ | FORMAT_SHOW_TIME));
@@ -67,113 +73,301 @@
assertEquals("12:00 PM", formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, FORMAT_12HOUR /*| FORMAT_NO_NOON*/ | FORMAT_SHOW_TIME));
assertEquals("12:00 AM", formatDateRange(en_US, tz, fixedTime - midnightDuration, fixedTime - midnightDuration, FORMAT_12HOUR | FORMAT_SHOW_TIME /*| FORMAT_NO_MIDNIGHT*/));
assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_SHOW_TIME | FORMAT_UTC));
- assertEquals("3 AM", formatDateRange(en_US, tz, fixedTime - integralDuration, fixedTime - integralDuration, FORMAT_SHOW_TIME | FORMAT_ABBREV_TIME));
- assertEquals("Mon", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY));
- assertEquals("Jan 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH));
- assertEquals("Jan 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("3 AM", formatDateRange(en_US, tz, onTheHour, onTheHour, FORMAT_SHOW_TIME | FORMAT_ABBREV_TIME));
+ assertEquals("Mon", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY));
+ assertEquals("Jan 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH));
+ assertEquals("Jan 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("1/19/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("1/19/2009 – 1/22/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("1/19/2009 – 4/22/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("1/19/2009 – 2/9/2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("1/19/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * HOUR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("1/19/2009 – 1/22/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("1/19/2009 – 4/22/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("1/19/2009 – 2/9/2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19.1.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19.01.2009 - 22.01.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19.01.2009 - 22.04.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19.01.2009 - 09.02.2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19.1.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19.01.2009 - 22.01.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19.01.2009 - 22.04.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19.01.2009 - 09.02.2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("1/19/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19/1/2009 – 22/1/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19/1/2009 – 22/4/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19/1/2009 – 9/2/2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("1/19/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19/1/2009 – 22/1/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19/1/2009 – 22/4/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19/1/2009 – 9/2/2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19/1/2009 – 22/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19/1/2009 – 22/4/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
- assertEquals("19/1/2009 – 9/2/2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19/1/2009 – 22/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19/1/2009 – 22/4/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+ assertEquals("19/1/2009 – 9/2/2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
// These are some random other test cases I came up with.
- assertEquals("January 19–22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
- assertEquals("Jan 19–22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("Mon, Jan 19 – Thu, Jan 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("Monday, January 19 – Thursday, January 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("January 19–22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, 0));
+ assertEquals("Jan 19–22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("Mon, Jan 19 – Thu, Jan 22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("Monday, January 19 – Thursday, January 22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
- assertEquals("January 19 – April 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
- assertEquals("Jan 19 – Apr 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("Mon, Jan 19 – Wed, Apr 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("January–April", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+ assertEquals("January 19 – April 22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, 0));
+ assertEquals("Jan 19 – Apr 22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("Mon, Jan 19 – Wed, Apr 22, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("January–April 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY));
- assertEquals("Jan 19, 2009 – Feb 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("Jan 2009 – Feb 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
- assertEquals("January 19, 2009 – February 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
- assertEquals("Monday, January 19, 2009 – Thursday, February 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("Jan 19, 2009 – Feb 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("Jan 2009 – Feb 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+ assertEquals("January 19, 2009 – February 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, 0));
+ assertEquals("Monday, January 19, 2009 – Thursday, February 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
// The same tests but for de_DE.
- assertEquals("19.-22. Januar", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
- assertEquals("19.-22. Jan.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("Mo., 19. - Do., 22. Jan.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("Montag, 19. - Donnerstag, 22. Januar", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("19.-22. Januar 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, 0));
+ assertEquals("19.-22. Jan. 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("Mo., 19. - Do., 22. Jan. 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("Montag, 19. - Donnerstag, 22. Januar 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
- assertEquals("19. Januar - 22. April", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
- assertEquals("19. Jan. - 22. Apr.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("Mo., 19. Jan. - Mi., 22. Apr.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("Januar-April", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+ assertEquals("19. Januar - 22. April 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, 0));
+ assertEquals("19. Jan. - 22. Apr. 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("Mo., 19. Jan. - Mi., 22. Apr. 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("Januar-April 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY));
- assertEquals("19. Jan. 2009 - 9. Feb. 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("Jan. 2009 - Feb. 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
- assertEquals("19. Januar 2009 - 9. Februar 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
- assertEquals("Montag, 19. Januar 2009 - Donnerstag, 9. Februar 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("19. Jan. 2009 - 9. Feb. 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("Jan. 2009 - Feb. 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+ assertEquals("19. Januar 2009 - 9. Februar 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, 0));
+ assertEquals("Montag, 19. Januar 2009 - Donnerstag, 9. Februar 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
// The same tests but for es_US.
- assertEquals("19–22 enero", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
- assertEquals("19–22 ene", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("lun 19 ene – jue 22 ene", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("lunes 19 enero – jueves 22 enero", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("19–22 enero 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, 0));
+ assertEquals("19–22 ene 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("lun 19 ene – jue 22 ene 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("lunes 19 enero – jueves 22 enero 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
- assertEquals("19 enero – 22 abril", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
- assertEquals("19 ene – 22 abr", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("lun 19 ene – mié 22 abr", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("enero–abril", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+ assertEquals("19 enero – 22 abril 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, 0));
+ assertEquals("19 ene – 22 abr 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("lun 19 ene – mié 22 abr 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("enero–abril 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY));
- assertEquals("19 ene 2009 – 9 feb 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("ene 2009 – feb 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
- assertEquals("19 enero 2009 – 9 febrero 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
- assertEquals("lunes 19 enero 2009 – jueves 9 febrero 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("19 ene 2009 – 9 feb 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("ene 2009 – feb 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+ assertEquals("19 enero 2009 – 9 febrero 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, 0));
+ assertEquals("lunes 19 enero 2009 – jueves 9 febrero 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
// The same tests but for es_ES.
- assertEquals("19–22 enero", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
- assertEquals("19–22 ene", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("lun 19 ene – jue 22 ene", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("lunes 19 enero – jueves 22 enero", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("19–22 enero 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, 0));
+ assertEquals("19–22 ene 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("lun 19 ene – jue 22 ene 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("lunes 19 enero – jueves 22 enero 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
- assertEquals("19 enero – 22 abril", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
- assertEquals("19 ene – 22 abr", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("lun 19 ene – mié 22 abr", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
- assertEquals("enero–abril", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+ assertEquals("19 enero – 22 abril 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, 0));
+ assertEquals("19 ene – 22 abr 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("lun 19 ene – mié 22 abr 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+ assertEquals("enero–abril 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY));
- assertEquals("19 ene 2009 – 9 feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
- assertEquals("ene 2009 – feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
- assertEquals("19 enero 2009 – 9 febrero 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
- assertEquals("lunes 19 enero 2009 – jueves 9 febrero 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+ assertEquals("19 ene 2009 – 9 feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ assertEquals("ene 2009 – feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+ assertEquals("19 enero 2009 – 9 febrero 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, 0));
+ assertEquals("lunes 19 enero 2009 – jueves 9 febrero 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
}
+ // http://b/8862241 - we should be able to format dates past 2038.
+ // See also http://code.google.com/p/android/issues/detail?id=13050.
public void test8862241() throws Exception {
- // Test the post-2038 future (http://b/8862241).
+ Locale l = Locale.US;
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
- long jan_19_2042 = new Date(2042 - 1900, 0, 19, 3, 30, 15).getTime();
- long oct_4_2046 = new Date(2046 - 1900, 9, 4, 3, 30, 15).getTime();
- assertEquals("Jan 19, 2042 – Oct 4, 2046", formatDateRange(Locale.US, tz, jan_19_2042, oct_4_2046, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+ Calendar c = Calendar.getInstance(tz, l);
+ c.set(2042, Calendar.JANUARY, 19, 3, 30);
+ long jan_19_2042 = c.getTimeInMillis();
+ c.set(2046, Calendar.OCTOBER, 4, 3, 30);
+ long oct_4_2046 = c.getTimeInMillis();
+ int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL;
+ assertEquals("Jan 19, 2042 – Oct 4, 2046", formatDateRange(l, tz, jan_19_2042, oct_4_2046, flags));
}
+ // http://b/10089890 - we should take the given time zone into account.
public void test10089890() throws Exception {
- // Test that we actually take the time zone into account.
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+ TimeZone pacific = TimeZone.getTimeZone("America/Los_Angeles");
+ int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL | FORMAT_SHOW_TIME | FORMAT_24HOUR;
+
// The Unix epoch is UTC, so 0 is 1970-01-01T00:00Z...
- assertEquals("Jan 1–2", formatDateRange(0, 24*60*60 * 1000L, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL, "Europe/London"));
+ assertEquals("Jan 1, 1970, 00:00 – Jan 2, 1970, 00:00", formatDateRange(l, utc, 0, DAY + 1, flags));
// But MTV is hours behind, so 0 was still the afternoon of the previous day...
- assertEquals("Dec 31, 1969 – Jan 1, 1970", formatDateRange(0, 24*60*60 * 1000L, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL, "America/Los_Angeles"));
+ assertEquals("Dec 31, 1969, 16:00 – Jan 1, 1970, 16:00", formatDateRange(l, pacific, 0, DAY, flags));
+ }
+
+ // http://b/10318326 - we can drop the minutes in a 12-hour time if they're zero,
+ // but not if we're using the 24-hour clock. That is: "4 PM" is reasonable, "16" is not.
+ public void test10318326() throws Exception {
+ long midnight = 0;
+ long teaTime = 16 * HOUR;
+
+ int time12 = FORMAT_12HOUR | FORMAT_SHOW_TIME;
+ int time24 = FORMAT_24HOUR | FORMAT_SHOW_TIME;
+ int abbr12 = time12 | FORMAT_ABBREV_ALL;
+ int abbr24 = time24 | FORMAT_ABBREV_ALL;
+
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+
+ // Full length on-the-hour times.
+ assertEquals("00:00", formatDateRange(l, utc, midnight, midnight, time24));
+ assertEquals("12:00 AM", formatDateRange(l, utc, midnight, midnight, time12));
+ assertEquals("16:00", formatDateRange(l, utc, teaTime, teaTime, time24));
+ assertEquals("4:00 PM", formatDateRange(l, utc, teaTime, teaTime, time12));
+
+ // Abbreviated on-the-hour times.
+ assertEquals("00:00", formatDateRange(l, utc, midnight, midnight, abbr24));
+ assertEquals("12 AM", formatDateRange(l, utc, midnight, midnight, abbr12));
+ assertEquals("16:00", formatDateRange(l, utc, teaTime, teaTime, abbr24));
+ assertEquals("4 PM", formatDateRange(l, utc, teaTime, teaTime, abbr12));
+
+ // Abbreviated on-the-hour ranges.
+ assertEquals("00:00–16:00", formatDateRange(l, utc, midnight, teaTime, abbr24));
+ assertEquals("12 AM – 4 PM", formatDateRange(l, utc, midnight, teaTime, abbr12));
+
+ // Abbreviated mixed ranges.
+ assertEquals("00:00–16:01", formatDateRange(l, utc, midnight, teaTime + MINUTE, abbr24));
+ assertEquals("12:00 AM – 4:01 PM", formatDateRange(l, utc, midnight, teaTime + MINUTE, abbr12));
+ }
+
+ // http://b/10560853 - when the time is not displayed, an end time 0 ms into the next day is
+ // considered to belong to the previous day.
+ public void test10560853_when_time_not_displayed() throws Exception {
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+
+ long midnight = 0;
+ long midnightNext = 1 * DAY;
+
+ int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY;
+
+ // An all-day event runs until 0 milliseconds into the next day, but is formatted as if it's
+ // just the first day.
+ assertEquals("Thursday, January 1, 1970", formatDateRange(l, utc, midnight, midnightNext, flags));
+
+ // Run one millisecond over, though, and you're into the next day.
+ long nextMorning = 1 * DAY + 1;
+ assertEquals("Thursday, January 1 – Friday, January 2, 1970", formatDateRange(l, utc, midnight, nextMorning, flags));
+
+ // But the same reasoning applies for that day.
+ long nextMidnight = 2 * DAY;
+ assertEquals("Thursday, January 1 – Friday, January 2, 1970", formatDateRange(l, utc, midnight, nextMidnight, flags));
+ }
+
+ // http://b/10560853 - when the start and end times are otherwise on the same day,
+ // an end time 0 ms into the next day is considered to belong to the previous day.
+ public void test10560853_for_single_day_events() throws Exception {
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+
+ int flags = FORMAT_SHOW_TIME | FORMAT_24HOUR | FORMAT_SHOW_DATE;
+
+ assertEquals("January 1, 1970, 22:00–00:00", formatDateRange(l, utc, 22 * HOUR, 24 * HOUR, flags));
+ assertEquals("January 1, 1970, 22:00 – January 2, 1970, 00:30", formatDateRange(l, utc, 22 * HOUR, 24 * HOUR + 30 * MINUTE, flags));
+ }
+
+ // http://b/10209343 - even if the caller didn't explicitly ask us to include the year,
+ // we should do so for years other than the current year.
+ public void test10209343_when_not_this_year() {
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+
+ int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_TIME | FORMAT_24HOUR;
+
+ assertEquals("Thursday, January 1, 1970, 00:00", formatDateRange(l, utc, 0L, 0L, flags));
+
+ long t1833 = ((long) Integer.MIN_VALUE + Integer.MIN_VALUE) * 1000L;
+ assertEquals("Sunday, November 24, 1833, 17:31", formatDateRange(l, utc, t1833, t1833, flags));
+
+ long t1901 = Integer.MIN_VALUE * 1000L;
+ assertEquals("Friday, December 13, 1901, 20:45", formatDateRange(l, utc, t1901, t1901, flags));
+
+ long t2038 = Integer.MAX_VALUE * 1000L;
+ assertEquals("Tuesday, January 19, 2038, 03:14", formatDateRange(l, utc, t2038, t2038, flags));
+
+ long t2106 = (2L + Integer.MAX_VALUE + Integer.MAX_VALUE) * 1000L;
+ assertEquals("Sunday, February 7, 2106, 06:28", formatDateRange(l, utc, t2106, t2106, flags));
+ }
+
+ // http://b/10209343 - for the current year, we should honor the FORMAT_SHOW_YEAR flags.
+ public void test10209343_when_this_year() {
+ // Construct a date in the current year (whenever the test happens to be run).
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+ Calendar c = Calendar.getInstance(utc, l);
+ c.set(Calendar.MONTH, Calendar.FEBRUARY);
+ c.set(Calendar.DAY_OF_MONTH, 10);
+ c.set(Calendar.HOUR_OF_DAY, 0);
+ long thisYear = c.getTimeInMillis();
+
+ // You don't get the year if it's this year...
+ assertEquals("February 10", formatDateRange(l, utc, thisYear, thisYear, FORMAT_SHOW_DATE));
+
+ // ...unless you explicitly ask for it.
+ assertEquals(String.format("February 10, %d", c.get(Calendar.YEAR)),
+ formatDateRange(l, utc, thisYear, thisYear, FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR));
+
+ // ...or it's not actually this year...
+ Calendar c2 = (Calendar) c.clone();
+ c2.set(Calendar.YEAR, 1980);
+ long oldYear = c2.getTimeInMillis();
+ assertEquals("February 10, 1980", formatDateRange(l, utc, oldYear, oldYear, FORMAT_SHOW_DATE));
+
+ // (But you can disable that!)
+ assertEquals("February 10", formatDateRange(l, utc, oldYear, oldYear, FORMAT_SHOW_DATE | FORMAT_NO_YEAR));
+
+ // ...or the start and end years aren't the same...
+ assertEquals(String.format("February 10, 1980 – February 10, %d", c.get(Calendar.YEAR)),
+ formatDateRange(l, utc, oldYear, thisYear, FORMAT_SHOW_DATE));
+
+ // (And you can't avoid that --- icu4c steps in and overrides you.)
+ assertEquals(String.format("February 10, 1980 – February 10, %d", c.get(Calendar.YEAR)),
+ formatDateRange(l, utc, oldYear, thisYear, FORMAT_SHOW_DATE | FORMAT_NO_YEAR));
+ }
+
+ // http://b/8467515 - yet another y2k38 bug report.
+ public void test8467515() throws Exception {
+ Locale l = Locale.US;
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+ int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH | FORMAT_ABBREV_WEEKDAY;
+ long t;
+
+ Calendar calendar = Calendar.getInstance(utc, l);
+ calendar.clear();
+
+ calendar.set(2038, Calendar.JANUARY, 19, 12, 0, 0);
+ t = calendar.getTimeInMillis();
+ assertEquals("Tue, Jan 19, 2038", formatDateRange(l, utc, t, t, flags));
+
+ calendar.set(1900, Calendar.JANUARY, 1, 0, 0, 0);
+ t = calendar.getTimeInMillis();
+ assertEquals("Mon, Jan 1, 1900", formatDateRange(l, utc, t, t, flags));
+ }
+
+ // http://b/12004664
+ public void test12004664() throws Exception {
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+ Calendar c = Calendar.getInstance(utc, Locale.US);
+ c.set(Calendar.YEAR, 1980);
+ c.set(Calendar.MONTH, Calendar.FEBRUARY);
+ c.set(Calendar.DAY_OF_MONTH, 10);
+ c.set(Calendar.HOUR_OF_DAY, 0);
+ long thisYear = c.getTimeInMillis();
+
+ int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_YEAR;
+ assertEquals("Sunday, February 10, 1980", formatDateRange(new Locale("en", "US"), utc, thisYear, thisYear, flags));
+
+ // If we supported non-Gregorian calendars, this is what that we'd expect for these locales.
+ // This is really the correct behavior, but since java.util.Calendar currently only supports
+ // the Gregorian calendar, we want to deliberately force icu4c to agree, otherwise we'd have
+ // a mix of calendars throughout an app's UI depending on whether Java or native code formatted
+ // the date.
+ //assertEquals("یکشنبه ۲۱ بهمن ۱۳۵۸ ه.ش.", formatDateRange(new Locale("fa"), utc, thisYear, thisYear, flags));
+ //assertEquals("AP ۱۳۵۸ سلواغه ۲۱, یکشنبه", formatDateRange(new Locale("ps"), utc, thisYear, thisYear, flags));
+ //assertEquals("วันอาทิตย์ 10 กุมภาพันธ์ 2523", formatDateRange(new Locale("th"), utc, thisYear, thisYear, flags));
+
+ // For now, here are the localized Gregorian strings instead...
+ assertEquals("یکشنبه ۱۰ فوریهٔ ۱۹۸۰", formatDateRange(new Locale("fa"), utc, thisYear, thisYear, flags));
+ assertEquals("یکشنبه د ۱۹۸۰ د فبروري ۱۰", formatDateRange(new Locale("ps"), utc, thisYear, thisYear, flags));
+ assertEquals("วันอาทิตย์ 10 กุมภาพันธ์ 1980", formatDateRange(new Locale("th"), utc, thisYear, thisYear, flags));
}
}
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 605fd63..e16496b 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -348,4 +348,13 @@
assertEquals("-w-o-r-l-d-", "hello world".substring(6).replace("", "-"));
assertEquals("-*-w-*-o-*-r-*-l-*-d-*-", "hello world".substring(6).replace("", "-*-"));
}
+
+ // http://b/11571917
+ public void test_String_getBytes() throws Exception {
+ assertEquals("[-126, -96]", Arrays.toString("あ".getBytes("Shift_JIS")));
+ assertEquals("[-126, -87]", Arrays.toString("か".getBytes("Shift_JIS")));
+ assertEquals("[-105, 67]", Arrays.toString("佑".getBytes("Shift_JIS")));
+ assertEquals("[36]", Arrays.toString("$".getBytes("Shift_JIS")));
+ assertEquals("[-29, -127, -117]", Arrays.toString("か".getBytes("UTF-8")));
+ }
}
diff --git a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
index bdde645..b7c4bc6 100644
--- a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
+++ b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
@@ -16,12 +16,17 @@
package libcore.java.net;
-import java.net.*;
-import java.util.Arrays;
+import junit.framework.TestCase;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
-import junit.framework.TestCase;
public class NetworkInterfaceTest extends TestCase {
// http://code.google.com/p/android/issues/detail?id=13784
@@ -36,6 +41,35 @@
assertEquals(expected, actual);
}
+ // http://code.google.com/p/android/issues/detail?id=34022
+ public void test_collectIpv6Addresses_3digitInterfaceIndex() throws Exception {
+ String lines[] = new String[] {
+ "fe800000000000000000000000000000 407 40 20 80 wlan0" };
+ List<InetAddress> addresses = new ArrayList<InetAddress>(1);
+ List<InterfaceAddress> ifAddresses = new ArrayList<InterfaceAddress>(1);
+
+ NetworkInterface.collectIpv6Addresses("wlan0", 1, addresses,
+ ifAddresses, lines);
+ assertEquals(1, addresses.size());
+ assertEquals(1, ifAddresses.size());
+ // Make sure the prefix length (field #3) is parsed correctly
+ assertEquals(4*16 + 0, ifAddresses.get(0).getNetworkPrefixLength());
+ }
+
+ public void test_collectIpv6Addresses_skipsUnmatchedLines() throws Exception {
+ String[] lines = new String[] {
+ "fe800000000000000000000000000000 40 40 20 80 wlan0",
+ "fe100000000000000000000000000000 41 40 20 80 wlan1",
+ "feb00000000000000000000000000000 42 40 20 80 wlan2" };
+ List<InetAddress> addresses = new ArrayList<InetAddress>(1);
+ List<InterfaceAddress> ifAddresses = new ArrayList<InterfaceAddress>(1);
+
+ NetworkInterface.collectIpv6Addresses("wlan0", 1, addresses,
+ ifAddresses, lines);
+ assertEquals(1, addresses.size());
+ assertEquals(1, ifAddresses.size());
+ }
+
public void testLoopback() throws Exception {
// We know lo shouldn't have a hardware address or an IPv4 broadcast address.
NetworkInterface lo = NetworkInterface.getByName("lo");
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 2e98e5f..4ed7f0e 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -78,6 +78,7 @@
import libcore.javax.net.ssl.TestSSLContext;
import tests.net.StuckServer;
+import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AFTER_READING_REQUEST;
import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;
@@ -338,39 +339,6 @@
assertEquals(0, server.takeRequest().getSequenceNumber());
}
- public void testRetryableRequestBodyAfterBrokenConnection() throws Exception {
- server.enqueue(new MockResponse().setBody("abc").setSocketPolicy(DISCONNECT_AT_END));
- server.enqueue(new MockResponse().setBody("def"));
- server.play();
-
- assertContent("abc", server.getUrl("/a").openConnection());
- HttpURLConnection connection = (HttpURLConnection) server.getUrl("/b").openConnection();
- connection.setDoOutput(true);
- OutputStream out = connection.getOutputStream();
- out.write(new byte[] {1, 2, 3});
- out.close();
- assertContent("def", connection);
- }
-
- public void testNonRetryableRequestBodyAfterBrokenConnection() throws Exception {
- server.enqueue(new MockResponse().setBody("abc").setSocketPolicy(DISCONNECT_AT_END));
- server.enqueue(new MockResponse().setBody("def"));
- server.play();
-
- assertContent("abc", server.getUrl("/a").openConnection());
- HttpURLConnection connection = (HttpURLConnection) server.getUrl("/b").openConnection();
- connection.setDoOutput(true);
- connection.setFixedLengthStreamingMode(3);
- OutputStream out = connection.getOutputStream();
- out.write(new byte[] {1, 2, 3});
- out.close();
- try {
- connection.getInputStream();
- fail();
- } catch (IOException expected) {
- }
- }
-
enum WriteKind { BYTE_BY_BYTE, SMALL_BUFFERS, LARGE_BUFFERS }
public void test_chunkedUpload_byteByByte() throws Exception {
@@ -511,30 +479,6 @@
}
}
- public void testConnectViaHttpsWithSSLFallback() throws IOException, InterruptedException {
- TestSSLContext testSSLContext = TestSSLContext.create();
-
- // This server socket factory only supports SSLv3. This is to avoid issues due to SCSV
- // checks. See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00
- SSLSocketFactory serverSocketFactory =
- new LimitedProtocolsSocketFactory(
- testSSLContext.serverContext.getSocketFactory(),
- "SSLv3");
-
- server.useHttps(serverSocketFactory, false);
- server.enqueue(new MockResponse().setSocketPolicy(DISCONNECT_AT_START));
- server.enqueue(new MockResponse().setBody("this response comes via SSL"));
- server.play();
-
- HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/foo").openConnection();
- connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-
- assertContent("this response comes via SSL", connection);
-
- RecordedRequest request = server.takeRequest();
- assertEquals("GET /foo HTTP/1.1", request.getRequestLine());
- }
-
/**
* Verify that we don't retry connections on certificate verification errors.
*
@@ -699,10 +643,17 @@
initResponseCache();
server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
- server.enqueue(new MockResponse()
+ MockResponse badProxyResponse = new MockResponse()
.setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)
.clearHeaders()
- .setBody("bogus proxy connect response content")); // Key to reproducing b/6754912
+ .setBody("bogus proxy connect response content"); // Key to reproducing b/6754912
+
+ // We enqueue the bad response twice because the connection will
+ // be retried with TLS_MODE_COMPATIBLE after the first connection
+ // fails.
+ server.enqueue(badProxyResponse);
+ server.enqueue(badProxyResponse);
+
server.play();
URL url = new URL("https://android.com/foo");
@@ -712,7 +663,7 @@
try {
connection.connect();
fail();
- } catch (IOException expected) {
+ } catch (SSLHandshakeException expected) {
// Thrown when the connect causes SSLSocket.startHandshake() to throw
// when it sees the "bogus proxy connect response content"
// instead of a ServerHello handshake message.
@@ -1392,11 +1343,37 @@
}
}
+ // bug 11473660
+ public void testAuthenticateWithLowerCaseHeadersAndScheme() throws Exception {
+ MockResponse pleaseAuthenticate = new MockResponse()
+ .setResponseCode(401)
+ .addHeader("www-authenticate: basic realm=\"protected area\"")
+ .setBody("Please authenticate.");
+ // fail auth three times...
+ server.enqueue(pleaseAuthenticate);
+ server.enqueue(pleaseAuthenticate);
+ server.enqueue(pleaseAuthenticate);
+ // ...then succeed the fourth time
+ server.enqueue(new MockResponse().setBody("Successful auth!"));
+ server.play();
+
+ SimpleAuthenticator authenticator = new SimpleAuthenticator();
+ Authenticator.setDefault(authenticator);
+ HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
+ assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals(Authenticator.RequestorType.SERVER, authenticator.requestorType);
+ assertEquals(server.getPort(), authenticator.requestingPort);
+ assertEquals(InetAddress.getByName(server.getHostName()), authenticator.requestingSite);
+ assertEquals("protected area", authenticator.requestingPrompt);
+ assertEquals("http", authenticator.requestingProtocol);
+ assertEquals("basic", authenticator.requestingScheme);
+ }
+
// http://code.google.com/p/android/issues/detail?id=19081
public void testAuthenticateWithCommaSeparatedAuthenticationMethods() throws Exception {
server.enqueue(new MockResponse()
.setResponseCode(401)
- .addHeader("WWW-Authenticate: Scheme1 realm=\"a\", Scheme2 realm=\"b\", "
+ .addHeader("WWW-Authenticate: Scheme1 realm=\"a\", Basic realm=\"b\", "
+ "Scheme3 realm=\"c\"")
.setBody("Please authenticate."));
server.enqueue(new MockResponse().setBody("Successful auth!"));
@@ -1410,15 +1387,15 @@
assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*");
assertContains(server.takeRequest().getHeaders(),
- "Authorization: Scheme2 " + SimpleAuthenticator.BASE_64_CREDENTIALS);
- assertEquals("Scheme2", authenticator.requestingScheme);
+ "Authorization: Basic " + SimpleAuthenticator.BASE_64_CREDENTIALS);
+ assertEquals("Basic", authenticator.requestingScheme);
}
public void testAuthenticateWithMultipleAuthenticationHeaders() throws Exception {
server.enqueue(new MockResponse()
.setResponseCode(401)
.addHeader("WWW-Authenticate: Scheme1 realm=\"a\"")
- .addHeader("WWW-Authenticate: Scheme2 realm=\"b\"")
+ .addHeader("WWW-Authenticate: Basic realm=\"b\"")
.addHeader("WWW-Authenticate: Scheme3 realm=\"c\"")
.setBody("Please authenticate."));
server.enqueue(new MockResponse().setBody("Successful auth!"));
@@ -1432,8 +1409,8 @@
assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*");
assertContains(server.takeRequest().getHeaders(),
- "Authorization: Scheme2 " + SimpleAuthenticator.BASE_64_CREDENTIALS);
- assertEquals("Scheme2", authenticator.requestingScheme);
+ "Authorization: Basic " + SimpleAuthenticator.BASE_64_CREDENTIALS);
+ assertEquals("Basic", authenticator.requestingScheme);
}
public void testRedirectedWithChunkedEncoding() throws Exception {
@@ -1652,9 +1629,12 @@
* addresses. This is typically one IPv4 address and one IPv6 address.
*/
public void testConnectTimeouts() throws IOException {
- StuckServer ss = new StuckServer(false);
+ StuckServer ss = new StuckServer(true);
int serverPort = ss.getLocalPort();
- URLConnection urlConnection = new URL("http://localhost:" + serverPort).openConnection();
+ String hostName = ss.getLocalSocketAddress().getAddress().getHostAddress();
+ URLConnection urlConnection = new URL("http://" + hostName + ":" + serverPort + "/")
+ .openConnection();
+
int timeout = 1000;
urlConnection.setConnectTimeout(timeout);
long start = System.currentTimeMillis();
@@ -1846,19 +1826,25 @@
}
}
- public void testGetKeepAlive() throws Exception {
+ public void testReadTimeoutsOnRecycledConnections() throws Exception {
server.enqueue(new MockResponse().setBody("ABC"));
server.play();
// The request should work once and then fail
URLConnection connection = server.getUrl("").openConnection();
+ // Read timeout of a day, sure to cause the test to timeout and fail.
+ connection.setReadTimeout(24 * 3600 * 1000);
InputStream input = connection.getInputStream();
assertEquals("ABC", readAscii(input, Integer.MAX_VALUE));
input.close();
try {
- server.getUrl("").openConnection().getInputStream();
+ connection = server.getUrl("").openConnection();
+ // Set the read timeout back to 100ms, this request will time out
+ // because we've only enqueued one response.
+ connection.setReadTimeout(100);
+ connection.getInputStream();
fail();
- } catch (ConnectException expected) {
+ } catch (IOException expected) {
}
}
@@ -1921,7 +1907,22 @@
}
public void testLenientUrlToUriNul() throws Exception {
- testUrlToUriMapping("\u0000", "%00", "%00", "%00", "%00"); // RI fails this
+ // On JB-MR2 and below, we would allow a host containing \u0000
+ // and then generate a request with a Host header that violated RFC2616.
+ // We now reject such hosts.
+ //
+ // The ideal behaviour here is to be "lenient" about the host and rewrite
+ // it, but attempting to do so introduces a new range of incompatible
+ // behaviours.
+ testUrlToUriMapping("\u0000", null, "%00", "%00", "%00"); // RI fails this
+ }
+
+ public void testHostWithNul() throws Exception {
+ URL url = new URL("http://host\u0000/");
+ try {
+ url.openStream();
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
private void testUrlToUriMapping(String string, String asAuthority, String asFile,
diff --git a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
index ec20c2a..b45f8e1 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
@@ -124,7 +124,7 @@
thread.start();
// select doesn't ever return, so await() times out and returns false
- assertFalse(selectReturned.await(500, TimeUnit.MILLISECONDS));
+ assertFalse(selectReturned.await(2, TimeUnit.SECONDS));
} finally {
selector.close();
}
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
deleted file mode 100644
index ddc2b29..0000000
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2010 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.java.nio.charset;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.util.Arrays;
-import java.util.ArrayList;
-
-public class CharsetTest extends junit.framework.TestCase {
- public void test_guaranteedCharsetsAvailable() throws Exception {
- // All Java implementations must support these charsets.
- assertNotNull(Charset.forName("ISO-8859-1"));
- assertNotNull(Charset.forName("US-ASCII"));
- assertNotNull(Charset.forName("UTF-16"));
- assertNotNull(Charset.forName("UTF-16BE"));
- assertNotNull(Charset.forName("UTF-16LE"));
- assertNotNull(Charset.forName("UTF-8"));
- }
-
- // http://code.google.com/p/android/issues/detail?id=42769
- public void test_42769() throws Exception {
- ArrayList<Thread> threads = new ArrayList<Thread>();
- for (int i = 0; i < 10; ++i) {
- Thread t = new Thread(new Runnable() {
- public void run() {
- for (int i = 0; i < 50; ++i) {
- Charset.availableCharsets();
- }
- }
- });
- threads.add(t);
- }
-
- for (Thread t : threads) {
- t.start();
- }
- for (Thread t : threads) {
- t.join();
- }
- }
-
- public void test_allAvailableCharsets() throws Exception {
- // Check that we can instantiate every Charset, CharsetDecoder, and CharsetEncoder.
- for (String charsetName : Charset.availableCharsets().keySet()) {
- if (charsetName.equals("UTF-32")) {
- // Our UTF-32 is broken. http://b/2702411
- // TODO: remove this hack when UTF-32 is fixed.
- continue;
- }
-
- Charset cs = Charset.forName(charsetName);
- assertNotNull(cs.newDecoder());
- if (cs.canEncode()) {
- CharsetEncoder enc = cs.newEncoder();
- assertNotNull(enc);
- assertNotNull(enc.replacement());
- }
- }
- }
-
- public void test_EUC_JP() throws Exception {
- assertEncodes(Charset.forName("EUC-JP"), "\ufffd", 0xf4, 0xfe);
- }
-
- public void test_SCSU() throws Exception {
- assertEncodes(Charset.forName("SCSU"), "\ufffd", 14, 0xff, 0xfd);
- }
-
- public void test_Shift_JIS() throws Exception {
- assertEncodes(Charset.forName("Shift_JIS"), "\ufffd", 0xfc, 0xfc);
- }
-
- public void test_UTF_16() throws Exception {
- Charset cs = Charset.forName("UTF-16");
- // Writes big-endian, with a big-endian BOM.
- assertEncodes(cs, "a\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
- // Reads whatever the BOM tells it to read...
- assertDecodes(cs, "a\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
- assertDecodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
- // ...and defaults to reading big-endian if there's no BOM.
- assertDecodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
- }
-
- public void test_UTF_16BE() throws Exception {
- Charset cs = Charset.forName("UTF-16BE");
- // Writes big-endian, with no BOM.
- assertEncodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
- // Treats a little-endian BOM as an error and continues to read big-endian.
- // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
- assertDecodes(cs, "\ufffda\u0666", 0xff, 0xfe, 0, 'a', 0x06, 0x66);
- // Accepts a big-endian BOM and includes U+FEFF in the decoded output.
- assertDecodes(cs, "\ufeffa\u0666", 0xfe, 0xff, 0, 'a', 0x06, 0x66);
- // Defaults to reading big-endian.
- assertDecodes(cs, "a\u0666", 0, 'a', 0x06, 0x66);
- }
-
- public void test_UTF_16LE() throws Exception {
- Charset cs = Charset.forName("UTF-16LE");
- // Writes little-endian, with no BOM.
- assertEncodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
- // Accepts a little-endian BOM and includes U+FEFF in the decoded output.
- assertDecodes(cs, "\ufeffa\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
- // Treats a big-endian BOM as an error and continues to read little-endian.
- // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
- assertDecodes(cs, "\ufffda\u0666", 0xfe, 0xff, 'a', 0, 0x66, 0x06);
- // Defaults to reading little-endian.
- assertDecodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
- }
-
- public void test_x_UTF_16LE_BOM() throws Exception {
- Charset cs = Charset.forName("x-UTF-16LE-BOM");
- // Writes little-endian, with a BOM.
- assertEncodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
- // Accepts a little-endian BOM and swallows the BOM.
- assertDecodes(cs, "a\u0666", 0xff, 0xfe, 'a', 0, 0x66, 0x06);
- // Swallows a big-endian BOM, but continues to read little-endian!
- assertDecodes(cs, "\u6100\u6606", 0xfe, 0xff, 'a', 0, 0x66, 0x06);
- // Defaults to reading little-endian.
- assertDecodes(cs, "a\u0666", 'a', 0, 0x66, 0x06);
- }
-
- public void test_UTF_32() throws Exception {
- Charset cs = Charset.forName("UTF-32");
- // Writes big-endian, with no BOM.
- assertEncodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- // Reads whatever the BOM tells it to read...
- assertDecodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- assertDecodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- // ...and defaults to reading big-endian if there's no BOM.
- assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- }
-
- public void test_UTF_32BE() throws Exception {
- Charset cs = Charset.forName("UTF-32BE");
- // Writes big-endian, with no BOM.
- assertEncodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- // Treats a little-endian BOM as an error and continues to read big-endian.
- // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
- assertDecodes(cs, "\ufffda\u0666", 0xff, 0xfe, 0, 0, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- // Accepts a big-endian BOM and swallows the BOM.
- assertDecodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- // Defaults to reading big-endian.
- assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- }
-
- public void test_UTF_32LE() throws Exception {
- Charset cs = Charset.forName("UTF-32LE");
- // Writes little-endian, with no BOM.
- assertEncodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- // Accepts a little-endian BOM and swallows the BOM.
- assertDecodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- // Treats a big-endian BOM as an error and continues to read little-endian.
- // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
- assertDecodes(cs, "\ufffda\u0666", 0, 0, 0xfe, 0xff, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- // Defaults to reading little-endian.
- assertDecodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- }
-
- public void test_X_UTF_32BE_BOM() throws Exception {
- Charset cs = Charset.forName("X-UTF-32BE-BOM");
- // Writes big-endian, with a big-endian BOM.
- assertEncodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- // Treats a little-endian BOM as an error and continues to read big-endian.
- // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
- assertDecodes(cs, "\ufffda\u0666", 0xff, 0xfe, 0, 0, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- // Swallows a big-endian BOM, and continues to read big-endian.
- assertDecodes(cs, "a\u0666", 0, 0, 0xfe, 0xff, 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- // Defaults to reading big-endian.
- assertDecodes(cs, "a\u0666", 0, 0, 0, 'a', 0, 0, 0x06, 0x66);
- }
-
- public void test_X_UTF_32LE_BOM() throws Exception {
- Charset cs = Charset.forName("X-UTF-32LE-BOM");
- // Writes little-endian, with a little-endian BOM.
- assertEncodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- // Accepts a little-endian BOM and swallows the BOM.
- assertDecodes(cs, "a\u0666", 0xff, 0xfe, 0, 0, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- // Treats a big-endian BOM as an error and continues to read little-endian.
- // This test uses REPLACE mode, so we get the U+FFFD replacement character in the result.
- assertDecodes(cs, "\ufffda\u0666", 0, 0, 0xfe, 0xff, 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- // Defaults to reading little-endian.
- assertDecodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
- }
-
- private byte[] toByteArray(int[] ints) {
- byte[] result = new byte[ints.length];
- for (int i = 0; i < ints.length; ++i) {
- result[i] = (byte) ints[i];
- }
- return result;
- }
-
- private void assertEncodes(Charset cs, String s, int... expectedByteInts) throws Exception {
- ByteBuffer out = cs.encode(s);
- byte[] bytes = new byte[out.remaining()];
- out.get(bytes);
- assertEquals(Arrays.toString(toByteArray(expectedByteInts)), Arrays.toString(bytes));
- }
-
- private void assertDecodes(Charset cs, String s, int... byteInts) throws Exception {
- ByteBuffer in = ByteBuffer.wrap(toByteArray(byteInts));
- CharBuffer out = cs.decode(in);
- assertEquals(s, out.toString());
- }
-}
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java
index 411727e..d4cf83e 100644
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java
@@ -177,7 +177,12 @@
encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
decoder.onMalformedInput(CodingErrorAction.REPORT);
CharBuffer inputCB = CharBuffer.allocate(65536);
- for (int code = 32; code <= 65533; code ++) {
+ for (int code = 32; code <= 65533; ++code) {
+ // icu4c seems to accept any surrogate as a sign that "more is coming",
+ // even for charsets like US-ASCII. http://b/10310751
+ if (code >= 0xd800 && code <= 0xdfff) {
+ continue;
+ }
if (encoder.canEncode((char) code)) {
inputCB.put((char) code);
}
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_GSM0338.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_GSM0338.java
deleted file mode 100644
index a8d2669..0000000
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_GSM0338.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.java.nio.charset;
-
-import java.nio.charset.CharacterCodingException;
-
-/** Note: this test is GSM specific */
-public class OldCharset_GSM0338 extends OldCharset_AbstractTest {
-
- @Override
- protected void setUp() throws Exception {
-// charsetName = "GSM0338";
- charsetName = "x-gsm-03.38-2000";
-
- testChars = theseChars(new int[]{
-10, 13, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
-46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
-78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 95, 97, 98,
-99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
-115, 116, 117, 118, 119, 120, 121, 122, 161, 163, 164, 165, 167, 191, 196, 197,
-198, 201, 209, 214, 216, 220, 223, 224, 228, 229, 230, 231, 232, 233, 236, 241,
-242, 246, 248, 249, 252, 915, 916
- });
-
- testBytes = theseBytes(new int[]{
-10, 13, 32, 33, 34, 35, 2, 37, 38, 39, 40, 41, 42, 43, 44, 45,
-46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-62, 63, 0, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
-78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 17, 97, 98,
-99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
-115, 116, 117, 118, 119, 120, 121, 122, 64, 1, 36, 3, 95, 96, 91, 14,
-28, 31, 93, 92, 11, 94, 30, 127, 123, 15, 29, 9, 4, 5, 7, 125,
-8, 124, 12, 6, 126, 19, 16
- });
-
- super.setUp();
- }
-
- @Override
- public void test_CodecDynamic () throws CharacterCodingException {
- }
-
-}
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_ISO_8859_16.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_ISO_8859_16.java
deleted file mode 100644
index edb219a..0000000
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_ISO_8859_16.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.java.nio.charset;
-
-/** Note: ICU only */
-public class OldCharset_ISO_8859_16 extends OldCharset_AbstractTest {
-
- @Override
- protected void setUp() throws Exception {
- charsetName = "ISO-8859-16";
-
- testChars = theseChars(new int[]{
-0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
-144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
-160, 167, 169, 171, 173, 176, 177, 182, 183, 187, 192, 193, 194, 196, 198, 199,
-200, 201, 202, 203, 204, 205, 206, 207, 210, 211, 212, 214, 217, 218, 219, 220,
-223, 224, 225, 226, 228, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 242,
-243, 244, 246, 249, 250, 251, 252, 255, 258, 321, 352, 382, 536, 8221, 8364
- });
-
- testBytes = theseBytes(new int[]{
-0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
-144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
-160, 167, 169, 171, 173, 176, 177, 182, 183, 187, 192, 193, 194, 196, 198, 199,
-200, 201, 202, 203, 204, 205, 206, 207, 210, 211, 212, 214, 217, 218, 219, 220,
-223, 224, 225, 226, 228, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 242,
-243, 244, 246, 249, 250, 251, 252, 255, 195, 163, 166, 184, 170, 181, 164
- });
-
- super.setUp();
- }
-
-}
diff --git a/luni/src/test/java/libcore/java/security/MessageDigestTest.java b/luni/src/test/java/libcore/java/security/MessageDigestTest.java
index cd7b8db..3646a7a 100644
--- a/luni/src/test/java/libcore/java/security/MessageDigestTest.java
+++ b/luni/src/test/java/libcore/java/security/MessageDigestTest.java
@@ -141,12 +141,9 @@
99, -71, 49, -67, 71, 65, 122, -127,
-91, 56, 50, 122, -7, 39, -38, 62 });
- // Regression test input for problem SHA-1 with input of
- // 256MBs. However, its currently too slow to be practical on
- // devices, so its disabled in that case. http://b/4501620
- boolean enabled256mb = (System.getProperty("os.arch").contains("x86") // host
- || System.getProperty("os.arch").contains("amd64")); // RI
- if (enabled256mb) {
+ // Regression test for a SHA-1 problem with inputs larger than 256 MiB. http://b/4501620
+ // In mid-2013 this takes 3 minutes even on the host, so let's not run it on devices.
+ if (System.getenv("ANDROID_BUILD_TOP") != null) {
// INPUT_256MB
putExpectation("MD2",
INPUT_256MB,
diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
index 21d7302..2813cee 100644
--- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
@@ -346,4 +346,11 @@
Date d2 = sdf.parse(formatted);
assertEquals(d, d2);
}
+
+ public void test_59383() throws Exception {
+ SimpleDateFormat sdf = new SimpleDateFormat("d. MMM yyyy H:mm", Locale.GERMAN);
+ sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
+ assertEquals(1376927400000L, sdf.parse("19. Aug 2013 8:50").getTime());
+ assertEquals(1376927400000L, sdf.parse("19. Aug. 2013 8:50").getTime());
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java b/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java
index 2e6905b..2a9e5ef 100644
--- a/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java
+++ b/luni/src/test/java/libcore/java/util/AbstractCollectionTest.java
@@ -26,8 +26,6 @@
// http://code.google.com/p/android/issues/detail?id=36519
public void test_toArray() throws Exception {
final ConcurrentHashMap<Integer, Integer> m = new ConcurrentHashMap<Integer, Integer>();
- assertTrue(m.values() instanceof AbstractCollection);
-
final AtomicBoolean finished = new AtomicBoolean(false);
Thread reader = new Thread(new Runnable() {
diff --git a/luni/src/test/java/libcore/java/util/CurrencyTest.java b/luni/src/test/java/libcore/java/util/CurrencyTest.java
index 8504eaf..61a22fd 100644
--- a/luni/src/test/java/libcore/java/util/CurrencyTest.java
+++ b/luni/src/test/java/libcore/java/util/CurrencyTest.java
@@ -59,8 +59,6 @@
assertEquals("Schweizer Franken", Currency.getInstance("CHF").getDisplayName(new Locale("de", "CH")));
assertEquals("franc suisse", Currency.getInstance("CHF").getDisplayName(new Locale("fr", "CH")));
assertEquals("Franco Svizzero", Currency.getInstance("CHF").getDisplayName(new Locale("it", "CH")));
- // Test behavior with unknown locales; should return the currency code.
- assertEquals("CHF", Currency.getInstance("CHF").getDisplayName(new Locale("xx", "YY")));
}
public void test_getDefaultFractionDigits() throws Exception {
diff --git a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
index 4bd858c..fa761d3 100644
--- a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
@@ -75,7 +75,6 @@
}
// This one makes sure we have all necessary locales installed.
- // Suppress this flaky test for now.
public void testICULocales() {
String[] locales = new String[] {
// List of locales currently required for Android.
@@ -131,7 +130,6 @@
"ISO-8859-13",
"ISO-8859-14",
"ISO-8859-15",
- "ISO-8859-16",
"ISO-2022-JP",
"Windows-950",
"Windows-1250",
@@ -153,32 +151,16 @@
"GBK",
"GB2312",
"EUC-KR",
+ "GSM0338"
+ };
- // Additional encoding not included in standard ICU.
- "GSM0338" };
+ for (String encoding : encodings) {
+ assertTrue("Charset " + encoding + " must be supported", Charset.isSupported(encoding));
- for (int i = 0; i < encodings.length; i++) {
- assertTrue("Charset " + encodings[i] + " must be supported",
- Charset.isSupported(encodings[i]));
-
- Charset cs = Charset.forName(encodings[i]);
-
+ Charset cs = Charset.forName(encoding);
Set<String> aliases = cs.aliases();
- System.out.println(aliases);
+ System.out.println(cs.name() + ": " + aliases);
}
-
- // Test for valid encoding that is not included in Android. IBM-37 is
- // a perfect candidate for this, as it is being used for mainframes and
- // thus somewhat out of the scope of Android.
- assertFalse("Charset IBM-37 must not be supported",
- Charset.isSupported("IBM-37"));
-
- // Test for a bogus encoding.
- assertFalse("Charset KLINGON must not be supported",
- Charset.isSupported("KLINGON"));
-
- // Check we have the canonical EUC-JP charset.
- assertEquals("EUC-JP", Charset.forName("EUC-JP").name());
}
}
diff --git a/luni/src/test/java/libcore/java/util/OldPriorityQueueTest.java b/luni/src/test/java/libcore/java/util/OldPriorityQueueTest.java
index de24cf9..26527aa 100644
--- a/luni/src/test/java/libcore/java/util/OldPriorityQueueTest.java
+++ b/luni/src/test/java/libcore/java/util/OldPriorityQueueTest.java
@@ -104,4 +104,20 @@
}
}
+ /**
+ * removeAt(.) must sometimes perform siftUp(.).
+ */
+ public void test_removeAt_siftUp() {
+ PriorityQueue<Integer> q = new PriorityQueue<Integer>();
+ // Adding a valid heap will keep elements in the same order
+ for (int i : new int[] { 0, 3, 1, 4, 5, 6, 2 }) {
+ q.add(i);
+ }
+ q.remove(4); // 2 replaces 4 but parent is 3, siftUp(.) is needed
+ for (int i : new int[] { 0, 1, 2, 3, 5, 6 }) {
+ assertEquals(i, (int) q.poll());
+ }
+ assertNull(q.poll());
+ }
+
}
diff --git a/luni/src/test/java/libcore/java/util/OldScannerTest.java b/luni/src/test/java/libcore/java/util/OldScannerTest.java
deleted file mode 100644
index 4f63d92..0000000
--- a/luni/src/test/java/libcore/java/util/OldScannerTest.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.java.util;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.StringReader;
-import java.net.InetSocketAddress;
-import java.nio.CharBuffer;
-import java.nio.channels.IllegalBlockingModeException;
-import java.nio.channels.ServerSocketChannel;
-import java.nio.channels.SocketChannel;
-import java.util.Arrays;
-import java.util.NoSuchElementException;
-import java.util.Scanner;
-import java.util.regex.MatchResult;
-import java.util.regex.Pattern;
-import junit.framework.TestCase;
-
-public final class OldScannerTest extends TestCase {
-
- public void test_findWithinHorizon_Ljava_lang_StringI() {
- // This method searches through the input up to the specified search
- // horizon(exclusive).
- Scanner s = new Scanner("123test");
- String result = s.findWithinHorizon("\\p{Lower}", 5);
- assertEquals("t", result);
- MatchResult mresult = s.match();
- assertEquals(3, mresult.start());
- assertEquals(4, mresult.end());
-
- s = new Scanner("12345test1234test next");
- /*
- * If the pattern is found the scanner advances past the input that
- * matched and returns the string that matched the pattern.
- */
- result = s.findWithinHorizon("\\p{Digit}+", 2);
- assertEquals("12", result);
- mresult = s.match();
- assertEquals(0, mresult.start());
- assertEquals(2, mresult.end());
- // Position is now pointing at the bar. "12|345test1234test next"
-
- result = s.findWithinHorizon("\\p{Digit}+", 6);
- assertEquals("345", result);
-
- mresult = s.match();
- assertEquals(2, mresult.start());
- assertEquals(5, mresult.end());
- // Position is now pointing at the bar. "12345|test1234test next"
-
- // If no such pattern is detected then the null is returned and the
- // scanner's position remains unchanged.
- result = s.findWithinHorizon("\\p{Digit}+", 3);
- assertNull(result);
-
- try {
- s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
- assertEquals("345", mresult.group());
- assertEquals(2, mresult.start());
- assertEquals(5, mresult.end());
- // Position is now still pointing at the bar. "12345|test1234test next"
-
- // If horizon is 0, then the horizon is ignored and this method
- // continues to search through the input looking for the specified
- // pattern without bound.
- result = s.findWithinHorizon("\\p{Digit}+", 0);
- mresult = s.match();
- assertEquals(9, mresult.start());
- assertEquals(13, mresult.end());
- // Position is now pointing at the bar. "12345test1234|test next"
-
- assertEquals("test", s.next());
- mresult = s.match();
- assertEquals(13, mresult.start());
- assertEquals(17, mresult.end());
-
- assertEquals("next", s.next());
- mresult = s.match();
- assertEquals(18, mresult.start());
- assertEquals(22, mresult.end());
-
- try {
- s.findWithinHorizon((String)null, 1);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
- }
-
- try {
- s.findWithinHorizon("\\p{Digit}+", -1);
- fail("Should throw IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- s.close();
- // on RI throws NullPointerException
- /*
- * try { System.out.println("fsdfs"); s.findWithinHorizon((String) null,
- * -1); System.out.println("fsdfs"); fail("Should throw
- * IllegalStateException"); } catch (IllegalStateException e) { //
- * expected }
- */
- s = new Scanner("test");
- result = s.findWithinHorizon("\\w+", 10);
- assertEquals("test", result);
-
- s = new Scanner("aa\n\rb");
- String patternStr = "^(a)$";
- result = s.findWithinHorizon("a", 5);
- assertEquals("a", result);
- mresult = s.match();
- assertEquals(0, mresult.start());
- assertEquals(1, mresult.end());
-
- result = s.findWithinHorizon(patternStr, 5);
- assertNull(result);
-
- try {
- mresult = s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
-
- s = new Scanner("");
- result = s.findWithinHorizon("^", 0);
- assertEquals("", result);
- MatchResult matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(0, matchResult.end());
-
- result = s.findWithinHorizon("$", 0);
- assertEquals("", result);
- matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(0, matchResult.end());
-
- s = new Scanner("1 fish 2 fish red fish blue fish");
- result = s.findWithinHorizon("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)", 10);
- assertNull(result);
-
- try {
- mresult = s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
- assertEquals(0, mresult.groupCount());
-
- result = s.findWithinHorizon("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)", 100);
- assertEquals("1 fish 2 fish red fish blue", result);
- mresult = s.match();
- assertEquals(4, mresult.groupCount());
- assertEquals("1", mresult.group(1));
- assertEquals("2", mresult.group(2));
- assertEquals("red", mresult.group(3));
- assertEquals("blue", mresult.group(4));
-
- s = new Scanner("test");
- s.close();
- try {
- s.findWithinHorizon("test", 1);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
-
- s = new Scanner("word1 WorD2 ");
- s.close();
- try {
- s.findWithinHorizon("\\d+", 10);
- fail("should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
-
- s = new Scanner("word1 WorD2 wOrd3 ");
- patternStr = "\\d+";
- assertEquals("1", s.findWithinHorizon(patternStr, 10));
- assertEquals("WorD2", s.next());
- assertEquals("3", s.findWithinHorizon(patternStr, 15));
-
- // Regression test
- s = new Scanner(new MockStringReader("MockStringReader"));
- patternStr = "test";
- result = s.findWithinHorizon(patternStr, 10);
- assertEquals("test", result);
-
- // Test the situation when input length is longer than buffer size.
- StringBuilder stringBuilder = new StringBuilder();
- for (int i = 0; i < 1026; i++) {
- stringBuilder.append('a');
- }
- s = new Scanner(stringBuilder.toString());
- patternStr = "\\p{Lower}+";
- result = s.findWithinHorizon(patternStr, 1026);
- assertEquals(stringBuilder.toString(), result);
-
- // Test the situation when input length is longer than buffer size and
- // set horizon to buffer size.
- stringBuilder = new StringBuilder();
- for (int i = 0; i < 1026; i++) {
- stringBuilder.append('a');
- }
- s = new Scanner(stringBuilder.toString());
- patternStr = "\\p{Lower}+";
- result = s.findWithinHorizon(patternStr, 1022);
- assertEquals(1022, result.length());
- assertEquals(stringBuilder.subSequence(0, 1022), result);
-
- // Test the situation, under which pattern is clipped by buffer.
- stringBuilder = new StringBuilder();
- for (int i = 0; i < 1022; i++) {
- stringBuilder.append(' ');
- }
- stringBuilder.append("bbc");
- assertEquals(1025, stringBuilder.length());
- s = new Scanner(stringBuilder.toString());
- patternStr = "bbc";
- result = s.findWithinHorizon(patternStr, 1025);
- assertEquals(3, result.length());
- assertEquals(stringBuilder.subSequence(1022, 1025), result);
-
- stringBuilder = new StringBuilder();
- for (int i = 0; i < 1026; i++) {
- stringBuilder.append('a');
- }
- s = new Scanner(stringBuilder.toString());
- patternStr = "\\p{Lower}+";
- result = s.findWithinHorizon(patternStr, 0);
- assertEquals(stringBuilder.toString(), result);
-
- stringBuilder = new StringBuilder();
- for (int i = 0; i < 10240; i++) {
- stringBuilder.append('-');
- }
- stringBuilder.replace(0, 2, "aa");
- s = new Scanner(stringBuilder.toString());
- result = s.findWithinHorizon("aa", 0);
- assertEquals("aa", result);
-
- s = new Scanner("aaaa");
- result = s.findWithinHorizon("a*", 0);
- assertEquals("aaaa", result);
- }
-
- public void test_findInLine_LString() {
- Scanner s = new Scanner("");
- String result = s.findInLine("^");
- assertEquals("", result);
- MatchResult matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(0, matchResult.end());
-
- result = s.findInLine("$");
- assertEquals("", result);
- matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(0, matchResult.end());
-
- /*
- * When we use the operation of findInLine(Pattern), the match region
- * should not span the line separator.
- */
- s = new Scanner("aa\nb.b");
- result = s.findInLine("a\nb*");
- assertNull(result);
-
- s = new Scanner("aa\nbb.b");
- result = s.findInLine("\\.");
- assertNull(result);
-
- s = new Scanner("abcd1234test\n");
- result = s.findInLine("\\p{Lower}+");
- assertEquals("abcd", result);
- matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(4, matchResult.end());
-
- result = s.findInLine("\\p{Digit}{5}");
- assertNull(result);
- try {
- matchResult = s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException expected) {
- }
- assertEquals(0, matchResult.start());
- assertEquals(4, matchResult.end());
-
- result = s.findInLine("\\p{Lower}+");
- assertEquals("test", result);
- matchResult = s.match();
- assertEquals(8, matchResult.start());
- assertEquals(12, matchResult.end());
-
- char[] chars = new char[2048];
- Arrays.fill(chars, 'a');
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(chars);
- stringBuilder.append("1234");
- s = new Scanner(stringBuilder.toString());
- result = s.findInLine("\\p{Digit}+");
- assertEquals("1234", result);
- matchResult = s.match();
- assertEquals(2048, matchResult.start());
- assertEquals(2052, matchResult.end());
-
- s = new Scanner("test1234\n1234 test");
- result = s.findInLine("test");
- assertEquals("test", result);
- matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(4, matchResult.end());
-
- int number = s.nextInt();
- assertEquals(1234, number);
- matchResult = s.match();
- assertEquals(4, matchResult.start());
- assertEquals(8, matchResult.end());
-
- result = s.next();
- assertEquals("1234", result);
- matchResult = s.match();
- assertEquals(9, matchResult.start());
- assertEquals(13, matchResult.end());
-
- result = s.findInLine("test");
- assertEquals("test", result);
- matchResult = s.match();
- assertEquals(14, matchResult.start());
- assertEquals(18, matchResult.end());
-
- s = new Scanner("test\u0085\ntest");
- result = s.findInLine("est");
- assertEquals("est", result);
- result = s.findInLine("est");
- assertEquals("est", result);
-
- s = new Scanner("test\ntest");
- result = s.findInLine("est");
- assertEquals("est", result);
- result = s.findInLine("est");
- assertEquals("est", result);
-
- s = new Scanner("test\n123\ntest");
- result = s.findInLine("est");
- assertEquals("est", result);
- result = s.findInLine("est");
- }
-
- public void test_Constructor_LReadableByteChannel() throws IOException {
- ServerSocketChannel ssc = ServerSocketChannel.open();
- ssc.socket().bind(null);
-
- SocketChannel sc = SocketChannel.open();
- sc.connect(ssc.socket().getLocalSocketAddress());
- sc.configureBlocking(false);
- assertFalse(sc.isBlocking());
-
- ssc.accept().close();
- ssc.close();
- assertFalse(sc.isBlocking());
-
- Scanner s = new Scanner(sc);
- try {
- s.hasNextInt();
- fail();
- } catch (IllegalBlockingModeException expected) {
- }
-
- sc.close();
- }
-
- private static class MockStringReader extends StringReader {
-
- public MockStringReader(String param) {
- super(param);
- }
-
- public int read(CharBuffer target) throws IOException {
- target.append('t');
- target.append('e');
- target.append('s');
- target.append('t');
- throw new IOException();
- }
- }
-
- // http://code.google.com/p/android/issues/detail?id=57050
- public void testPerformance() throws Exception {
- int count = 100000;
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- BufferedWriter out = new BufferedWriter(new OutputStreamWriter(baos));
- for (int i = 0; i < count; ++i) {
- out.write(Integer.toString(123) + " ");
- }
- out.close();
-
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- bais.mark(-1);
-
- Scanner s = new Scanner(new BufferedReader(new InputStreamReader(bais)));
- for (int i = 0; i < count; ++i) {
- if (s.nextInt() != 123) {
- fail();
- }
- }
-
- bais.reset();
- s = new Scanner(new BufferedReader(new InputStreamReader(bais)));
- for (int i = 0; i < count; ++i) {
- if (s.nextFloat() != 123.0) {
- fail();
- }
- }
- }
-}
diff --git a/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java b/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
index 56bb651..b69a2dd 100644
--- a/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
+++ b/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
@@ -17,23 +17,54 @@
package libcore.java.util;
import java.util.Iterator;
+import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
public class ServiceLoaderTest extends junit.framework.TestCase {
- public static interface UnimplementedInterface { }
- public void test_noImplementations() {
- assertFalse(ServiceLoader.load(UnimplementedInterface.class).iterator().hasNext());
- }
+ public static interface UnimplementedInterface { }
+ public void test_noImplementations() {
+ assertFalse(ServiceLoader.load(UnimplementedInterface.class).iterator().hasNext());
+ }
- public static class Impl1 implements ServiceLoaderTestInterface { }
- public static class Impl2 implements ServiceLoaderTestInterface { }
- public void test_implementations() {
- ServiceLoader<ServiceLoaderTestInterface> loader = ServiceLoader.load(ServiceLoaderTestInterface.class);
- Iterator<ServiceLoaderTestInterface> it = loader.iterator();
- assertTrue(it.hasNext());
- assertTrue(it.next() instanceof Impl1);
- assertTrue(it.hasNext());
- assertTrue(it.next() instanceof Impl2);
- assertFalse(it.hasNext());
+ public static class Impl1 implements ServiceLoaderTestInterface { }
+ public static class Impl2 implements ServiceLoaderTestInterface { }
+ public void test_implementations() {
+ ServiceLoader<ServiceLoaderTestInterface> loader = ServiceLoader.load(ServiceLoaderTestInterface.class);
+ Iterator<ServiceLoaderTestInterface> it = loader.iterator();
+ assertTrue(it.hasNext());
+ assertTrue(it.next() instanceof Impl1);
+ assertTrue(it.hasNext());
+ assertTrue(it.next() instanceof Impl2);
+ assertFalse(it.hasNext());
+ }
+
+ // Something like "does.not.Exist", that is a well-formed class name, but just doesn't exist.
+ public void test_missingRegisteredClass() throws Exception {
+ try {
+ ServiceLoader.load(ServiceLoaderTestInterfaceMissingClass.class).iterator().next();
+ fail();
+ } catch (ServiceConfigurationError expected) {
+ assertTrue(expected.getCause() instanceof ClassNotFoundException);
}
+ }
+
+ // Something like "java.lang.String", that is a class that exists,
+ // but doesn't implement the interface.
+ public void test_wrongTypeRegisteredClass() throws Exception {
+ try {
+ ServiceLoader.load(ServiceLoaderTestInterfaceWrongType.class).iterator().next();
+ fail();
+ } catch (ServiceConfigurationError expected) {
+ assertTrue(expected.getCause() instanceof ClassCastException);
+ }
+ }
+
+ // Something like "This is not a class name!" that's just a parse error.
+ public void test_invalidRegisteredClass() throws Exception {
+ try {
+ ServiceLoader.load(ServiceLoaderTestInterfaceParseError.class).iterator().next();
+ fail();
+ } catch (ServiceConfigurationError expected) {
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceMissingClass.java b/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceMissingClass.java
new file mode 100644
index 0000000..e2ceffd
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceMissingClass.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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.java.util;
+
+/**
+ * Ideally, this would have been an inner class in ServiceLoaderTest, but we need a corresponding
+ * resource file, and our build system can't cope with $ in filenames.
+ */
+public interface ServiceLoaderTestInterfaceMissingClass {
+}
diff --git a/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceParseError.java b/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceParseError.java
new file mode 100644
index 0000000..2a4dfcc
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceParseError.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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.java.util;
+
+/**
+ * Ideally, this would have been an inner class in ServiceLoaderTest, but we need a corresponding
+ * resource file, and our build system can't cope with $ in filenames.
+ */
+public interface ServiceLoaderTestInterfaceParseError {
+}
diff --git a/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceWrongType.java b/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceWrongType.java
new file mode 100644
index 0000000..7d3ddd4
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ServiceLoaderTestInterfaceWrongType.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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.java.util;
+
+/**
+ * Ideally, this would have been an inner class in ServiceLoaderTest, but we need a corresponding
+ * resource file, and our build system can't cope with $ in filenames.
+ */
+public interface ServiceLoaderTestInterfaceWrongType {
+}
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java b/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java
index 0845b32..550ddfb 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java
@@ -169,4 +169,27 @@
assertEquals(maxLengthComment, zipFile.getEntry("x").getComment());
zipFile.close();
}
+
+ public void testCommentAndExtraInSameOrder() throws Exception {
+ String comment = makeString(17, "z");
+ byte[] extra = makeString(11, "a").getBytes();
+
+ File f = createTemporaryZipFile();
+ ZipOutputStream out = createZipOutputStream(f);
+ ZipEntry ze = new ZipEntry("x");
+ ze.setExtra(extra);
+ ze.setComment(comment);
+ out.putNextEntry(ze);
+ out.closeEntry();
+ out.close();
+
+ // Read it back and make sure comments and extra are in the right order
+ ZipFile zipFile = new ZipFile(f);
+ try {
+ assertEquals(comment, zipFile.getEntry("x").getComment());
+ assertTrue(Arrays.equals(extra, zipFile.getEntry("x").getExtra()));
+ } finally {
+ zipFile.close();
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
index cad881b..60af4d0 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
@@ -118,6 +118,51 @@
}
}
+ /**
+ * Make sure the size used for stored zip entires is the uncompressed size.
+ * b/10227498
+ */
+ public void testStoredEntrySize() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ZipOutputStream out = new ZipOutputStream(baos);
+
+ // Set up a single stored entry.
+ String name = "test_file";
+ int expectedLength = 5;
+ ZipEntry outEntry = new ZipEntry(name);
+ byte[] buffer = new byte[expectedLength];
+ outEntry.setMethod(ZipEntry.STORED);
+ CRC32 crc = new CRC32();
+ crc.update(buffer);
+ outEntry.setCrc(crc.getValue());
+ outEntry.setSize(buffer.length);
+
+ out.putNextEntry(outEntry);
+ out.write(buffer);
+ out.closeEntry();
+ out.close();
+
+ // Write the result to a file.
+ byte[] outBuffer = baos.toByteArray();
+ File zipFile = createTemporaryZipFile();
+ writeBytes(zipFile, outBuffer);
+
+ ZipFile zip = new ZipFile(zipFile);
+ // Set up the zip entry to have different compressed/uncompressed sizes.
+ ZipEntry ze = zip.getEntry(name);
+ ze.setCompressedSize(expectedLength - 1);
+ // Read the contents of the stream and verify uncompressed size was used.
+ InputStream stream = zip.getInputStream(ze);
+ int count = 0;
+ int read;
+ while ((read = stream.read(buffer)) != -1) {
+ count += read;
+ }
+
+ assertEquals(expectedLength, count);
+
+ }
+
public void testInflatingStreamsRequiringZipRefill() throws IOException {
int originalSize = 1024 * 1024;
byte[] readBuffer = new byte[8192];
@@ -378,35 +423,6 @@
assertEquals(null, zipFile.getComment());
}
- public void testNameLengthChecks() throws IOException {
- // Is entry name length checking done on bytes or characters?
- // Really it should be bytes, but the RI only checks characters at construction time.
- // Android does the same, because it's cheap...
- try {
- new ZipEntry((String) null);
- fail();
- } catch (NullPointerException expected) {
- }
- new ZipEntry(makeString(0xffff, "a"));
- try {
- new ZipEntry(makeString(0xffff + 1, "a"));
- fail();
- } catch (IllegalArgumentException expected) {
- }
-
- // ...but Android won't let you create a zip file with a truncated name.
- ZipOutputStream out = createZipOutputStream(createTemporaryZipFile());
- ZipEntry ze = new ZipEntry(makeString(0xffff, "\u0666"));
- try {
- out.putNextEntry(ze);
- fail(); // The RI fails this test; it just checks the character count at construction time.
- } catch (IllegalArgumentException expected) {
- }
- out.closeEntry();
- out.putNextEntry(new ZipEntry("okay")); // ZipOutputStream.close throws if you add nothing!
- out.close();
- }
-
// https://code.google.com/p/android/issues/detail?id=58465
public void test_NUL_in_filename() throws Exception {
File file = createTemporaryZipFile();
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherInputStreamTest.java b/luni/src/test/java/libcore/javax/crypto/CipherInputStreamTest.java
index 40fd8fd..28d95f2 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherInputStreamTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherInputStreamTest.java
@@ -24,6 +24,7 @@
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import junit.framework.TestCase;
@@ -71,4 +72,13 @@
}
return out.toByteArray();
}
+
+ public void testCipherInputStream_TruncatedInput_Failure() throws Exception {
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(new byte[16], "AES"),
+ new IvParameterSpec(new byte[16]));
+ InputStream is = new CipherInputStream(new ByteArrayInputStream(new byte[31]), cipher);
+ is.read(new byte[4]);
+ is.close();
+ }
}
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index dac43a2..7922a04 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -21,6 +21,7 @@
import java.io.PrintStream;
import java.math.BigInteger;
import java.nio.ByteBuffer;
+import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -778,8 +779,10 @@
// Cipher.getInstance(String)
Cipher c1 = Cipher.getInstance(algorithm);
- assertEquals(algorithm, c1.getAlgorithm());
- test_Cipher(c1);
+ if (provider.equals(c1.getProvider())) {
+ assertEquals(algorithm, c1.getAlgorithm());
+ test_Cipher(c1);
+ }
// Cipher.getInstance(String, Provider)
Cipher c2 = Cipher.getInstance(algorithm, provider);
@@ -812,6 +815,23 @@
final AlgorithmParameterSpec encryptSpec = getEncryptAlgorithmParameterSpec(algorithm);
int encryptMode = getEncryptMode(algorithm);
+
+ // Bouncycastle doesn't return a default PBEParameterSpec
+ if (isPBE(algorithm) && !"BC".equals(providerName)) {
+ assertNotNull(cipherID + " getParameters()", c.getParameters());
+ assertNotNull(c.getParameters().getParameterSpec(PBEParameterSpec.class));
+ } else {
+ assertNull(cipherID + " getParameters()", c.getParameters());
+ }
+ try {
+ assertNull(cipherID + " getIV()", c.getIV());
+ } catch (NullPointerException e) {
+ // Bouncycastle apparently has a bug here with AESWRAP, et al.
+ if (!("BC".equals(providerName) && isOnlyWrappingAlgorithm(algorithm))) {
+ throw e;
+ }
+ }
+
c.init(encryptMode, encryptKey, encryptSpec);
assertEquals(cipherID + " getBlockSize() encryptMode",
getExpectedBlockSize(algorithm, encryptMode, providerName), c.getBlockSize());
@@ -826,9 +846,41 @@
assertEquals(cipherID + " getOutputSize(0) decryptMode",
getExpectedOutputSize(algorithm, decryptMode, providerName), c.getOutputSize(0));
- // TODO: test Cipher.getIV()
+ if (isPBE(algorithm)) {
+ if (algorithm.endsWith("RC4")) {
+ assertNull(cipherID + " getIV()", c.getIV());
+ } else {
+ assertNotNull(cipherID + " getIV()", c.getIV());
+ }
+ } else if (decryptSpec instanceof IvParameterSpec) {
+ assertEquals(cipherID + " getIV()",
+ Arrays.toString(((IvParameterSpec) decryptSpec).getIV()),
+ Arrays.toString(c.getIV()));
+ } else {
+ try {
+ assertNull(cipherID + " getIV()", c.getIV());
+ } catch (NullPointerException e) {
+ // Bouncycastle apparently has a bug here with AESWRAP, et al.
+ if (!("BC".equals(providerName) && isOnlyWrappingAlgorithm(algorithm))) {
+ throw e;
+ }
+ }
+ }
- // TODO: test Cipher.getParameters()
+ AlgorithmParameters params = c.getParameters();
+ if (decryptSpec == null) {
+ assertNull(cipherID + " getParameters()", params);
+ } else if (decryptSpec instanceof IvParameterSpec) {
+ IvParameterSpec ivDecryptSpec = (IvParameterSpec) params.getParameterSpec(IvParameterSpec.class);
+ assertEquals(cipherID + " getIV()",
+ Arrays.toString(((IvParameterSpec) decryptSpec).getIV()),
+ Arrays.toString(ivDecryptSpec.getIV()));
+ } else if (decryptSpec instanceof PBEParameterSpec) {
+ // Bouncycastle seems to be schizophrenic about whther it returns this or not
+ if (!"BC".equals(providerName)) {
+ assertNotNull(cipherID + " getParameters()", params);
+ }
+ }
assertNull(cipherID, c.getExemptionMechanism());
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java
index 67c83bf..ba048a8 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSessionTest.java
@@ -96,7 +96,9 @@
assertTrue(s.invalid.getLastAccessedTime() > 0);
assertTrue(s.server.getLastAccessedTime() > 0);
assertTrue(s.client.getLastAccessedTime() > 0);
- assertTrue(Math.abs(s.server.getLastAccessedTime()
+ assertTrue("s.server.getLastAccessedTime()=" + s.server.getLastAccessedTime() + " " +
+ "s.client.getLastAccessedTime()=" + s.client.getLastAccessedTime(),
+ Math.abs(s.server.getLastAccessedTime()
- s.client.getLastAccessedTime()) < 1 * 1000);
assertTrue(s.server.getLastAccessedTime() >=
s.server.getCreationTime());
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index 678ecf0..8e009bd 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -21,6 +21,7 @@
import java.io.OutputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Method;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
@@ -47,6 +48,7 @@
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLProtocolException;
+import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
@@ -1246,41 +1248,105 @@
c.close();
}
- public void test_SSLSocket_interrupt() throws Exception {
- ServerSocket listening = new ServerSocket(0);
-
- for (int i = 0; i < 3; i++) {
- Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
- Socket server = listening.accept();
-
- SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
- Socket clientWrapping = sf.createSocket(underlying, null, -1, true);
-
- switch (i) {
- case 0:
- test_SSLSocket_interrupt_case(underlying, underlying);
- break;
- case 1:
- test_SSLSocket_interrupt_case(underlying, clientWrapping);
- break;
- case 2:
- test_SSLSocket_interrupt_case(clientWrapping, underlying);
- break;
- case 3:
- test_SSLSocket_interrupt_case(clientWrapping, clientWrapping);
- break;
- default:
- fail();
- }
-
- server.close();
- underlying.close();
+ public void test_SSLSocket_reusedNpnSocket() throws Exception {
+ if (StandardNames.IS_RI) {
+ // RI does not support NPN/ALPN
+ return;
}
- listening.close();
+
+ byte[] npnProtocols = new byte[] {
+ 8, 'h', 't', 't', 'p', '/', '1', '.', '1'
+ };
+
+ final TestSSLContext c = TestSSLContext.create();
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
+
+ // Reflection is used so this can compile on the RI
+ String expectedClassName = "com.android.org.conscrypt.OpenSSLSocketImpl";
+ Class<?> actualClass = client.getClass();
+ assertEquals(expectedClassName, actualClass.getName());
+ Method setNpnProtocols = actualClass.getMethod("setNpnProtocols", byte[].class);
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ // First connection with NPN set on client and server
+ {
+ setNpnProtocols.invoke(client, npnProtocols);
+ client.connect(new InetSocketAddress(c.host, c.port));
+
+ final SSLSocket server = (SSLSocket) c.serverSocket.accept();
+ assertEquals(expectedClassName, server.getClass().getName());
+ setNpnProtocols.invoke(server, npnProtocols);
+
+ Future<Void> future = executor.submit(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ server.startHandshake();
+ return null;
+ }
+ });
+ client.startHandshake();
+
+ future.get();
+ client.close();
+ server.close();
+ }
+
+ // Second connection with client NPN already set on the SSL context, but
+ // without server NPN set.
+ {
+ SSLServerSocket serverSocket = (SSLServerSocket) c.serverContext
+ .getServerSocketFactory().createServerSocket(0);
+ InetAddress host = InetAddress.getLocalHost();
+ int port = serverSocket.getLocalPort();
+
+ client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
+ client.connect(new InetSocketAddress(host, port));
+
+ final SSLSocket server = (SSLSocket) serverSocket.accept();
+
+ Future<Void> future = executor.submit(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ server.startHandshake();
+ return null;
+ }
+ });
+ client.startHandshake();
+
+ future.get();
+ client.close();
+ server.close();
+ serverSocket.close();
+ }
+
+ c.close();
}
- private void test_SSLSocket_interrupt_case(Socket toRead, final Socket toClose)
+ public void test_SSLSocket_interrupt() throws Exception {
+ test_SSLSocket_interrupt_case(true, true);
+ test_SSLSocket_interrupt_case(true, false);
+ test_SSLSocket_interrupt_case(false, true);
+ // Currently failing due to reader blocking closing thread http://b/10681815
+ if (StandardNames.IS_RI) {
+ test_SSLSocket_interrupt_case(false, false);
+ }
+ }
+
+ private void test_SSLSocket_interrupt_case(boolean readUnderlying, boolean closeUnderlying)
throws Exception {
+
+ ServerSocket listening = new ServerSocket(0);
+
+ Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
+ Socket server = listening.accept();
+
+ SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ Socket clientWrapping = sf.createSocket(underlying, null, -1, true);
+
+ final Socket toRead = (readUnderlying) ? underlying : clientWrapping;
+ final Socket toClose = (closeUnderlying) ? underlying : clientWrapping;
+
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(new Callable<Void>() {
@Override public Void call() throws Exception {
@@ -1299,6 +1365,10 @@
} catch (SocketException expected) {
}
future.get();
+
+ server.close();
+ underlying.close();
+ listening.close();
}
/**
diff --git a/luni/src/test/java/libcore/javax/net/ssl/X509KeyManagerTest.java b/luni/src/test/java/libcore/javax/net/ssl/X509KeyManagerTest.java
new file mode 100644
index 0000000..a44edd0
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/net/ssl/X509KeyManagerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2013 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.javax.net.ssl;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.X509KeyManager;
+
+import junit.framework.TestCase;
+import libcore.java.security.TestKeyStore;
+
+public class X509KeyManagerTest extends TestCase {
+ /**
+ * Tests whether the key manager will select the right key when the CA is of
+ * one key type and the client is of a possibly different key type.
+ *
+ * <p>There was a bug where EC was being interpreted as EC_EC and only
+ * accepting EC signatures when it should accept any signature type.
+ */
+ public void testChooseClientAlias_Combinations() throws Exception {
+ test_ChooseClientAlias_KeyType("RSA", "RSA", "RSA", true);
+ test_ChooseClientAlias_KeyType("RSA", "EC", "RSA", true);
+ test_ChooseClientAlias_KeyType("RSA", "EC", "EC", false);
+
+ test_ChooseClientAlias_KeyType("EC", "RSA", "EC_RSA", true);
+ test_ChooseClientAlias_KeyType("EC", "EC", "EC_RSA", false);
+
+ test_ChooseClientAlias_KeyType("EC", "EC", "EC_EC", true);
+ test_ChooseClientAlias_KeyType("EC", "RSA", "EC_EC", false);
+
+ test_ChooseClientAlias_KeyType("EC", "RSA", "RSA", false);
+ }
+
+ private void test_ChooseClientAlias_KeyType(String clientKeyType, String caKeyType,
+ String selectedKeyType, boolean succeeds) throws Exception {
+ TestKeyStore ca = new TestKeyStore.Builder()
+ .keyAlgorithms(caKeyType)
+ .build();
+ TestKeyStore client = new TestKeyStore.Builder().keyAlgorithms(clientKeyType)
+ .signer(ca.getPrivateKey(caKeyType, caKeyType))
+ .build();
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
+ .getDefaultAlgorithm());
+ kmf.init(client.keyStore, client.keyPassword);
+
+ String[] keyTypes = new String[] { selectedKeyType };
+ KeyManager[] managers = kmf.getKeyManagers();
+ for (KeyManager manager : managers) {
+ if (manager instanceof X509KeyManager) {
+ String alias = ((X509KeyManager) manager).chooseClientAlias(keyTypes, null, null);
+ if (succeeds) {
+ assertNotNull(alias);
+ } else {
+ assertNull(alias);
+ }
+ }
+ }
+ }
+}
diff --git a/luni/src/test/java/libcore/util/ZoneInfoDBTest.java b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
index d5f2b6e..28ae416 100644
--- a/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
+++ b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
@@ -23,18 +23,22 @@
public class ZoneInfoDBTest extends junit.framework.TestCase {
private static final String CURRENT_VERSION = ZoneInfoDB.getInstance().getVersion();
- private static final String DEFAULT_FILE = System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata";
+
+ // Any new file in /data...
+ private static final String TZDATA_IN_DATA = System.getenv("ANDROID_DATA") + "/misc/zoneinfo/tzdata";
+ // ...overrides any existing file in /system.
+ private static final String TZDATA_IN_ROOT = System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata";
// An empty override file should fall back to the default file.
public void testEmptyOverrideFile() throws Exception {
- ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeEmptyFile(), DEFAULT_FILE);
+ ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeEmptyFile(), TZDATA_IN_DATA, TZDATA_IN_ROOT);
assertEquals(CURRENT_VERSION, data.getVersion());
assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
}
// A corrupt override file should fall back to the default file.
public void testCorruptOverrideFile() throws Exception {
- ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeCorruptFile(), DEFAULT_FILE);
+ ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeCorruptFile(), TZDATA_IN_DATA, TZDATA_IN_ROOT);
assertEquals(CURRENT_VERSION, data.getVersion());
assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
}
@@ -49,9 +53,11 @@
// Given a valid override file, we should find ourselves using that.
public void testGoodOverrideFile() throws Exception {
- RandomAccessFile in = new RandomAccessFile(DEFAULT_FILE, "r");
+ // We copy /system/usr/share/zoneinfo/tzdata because we know that always exists.
+ RandomAccessFile in = new RandomAccessFile(TZDATA_IN_ROOT, "r");
byte[] content = new byte[(int) in.length()];
in.readFully(content);
+ // Bump the version number to one long past where humans will be extinct.
content[6] = '9';
content[7] = '9';
content[8] = '9';
@@ -61,7 +67,7 @@
String goodFile = makeTemporaryFile(content);
try {
- ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(goodFile, DEFAULT_FILE);
+ ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(goodFile, TZDATA_IN_DATA, TZDATA_IN_ROOT);
assertEquals("9999z", data.getVersion());
assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
} finally {
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java
index dcd50bb..5d8c621 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java
@@ -261,6 +261,10 @@
assertTrue("Connection does not use proxy",
connection.usingProxy());
assertTrue("Proxy server was not used", proxy.accepted);
+
+ connection.disconnect();
+ assertTrue("usingProxy broken after disconnect",
+ connection.usingProxy());
} finally {
// restore default proxy selector
ProxySelector.setDefault(defPS);
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java
index 1c86303..aa2d9ca 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java
@@ -65,4 +65,19 @@
} catch (UnsupportedCharsetException expected) {
}
}
+
+ // http://b/11571917
+ public void test11571917() throws Exception {
+ assertEquals("%82%A0", URLEncoder.encode("あ", "Shift_JIS"));
+ assertEquals("%82%A9", URLEncoder.encode("か", "Shift_JIS"));
+ assertEquals("%97%43", URLEncoder.encode("佑", "Shift_JIS"));
+ assertEquals("%24", URLEncoder.encode("$", "Shift_JIS"));
+ assertEquals("%E3%81%8B", URLEncoder.encode("か", "UTF-8"));
+
+ assertEquals("%82%A0%82%A9%97%43%24%E3%81%8B", URLEncoder.encode("あ", "Shift_JIS") +
+ URLEncoder.encode("か", "Shift_JIS") +
+ URLEncoder.encode("佑", "Shift_JIS") +
+ URLEncoder.encode("$", "Shift_JIS") +
+ URLEncoder.encode("か", "UTF-8"));
+ }
}
diff --git a/luni/src/test/resources/META-INF/services/java.nio.charset.spi.CharsetProvider b/luni/src/test/resources/META-INF/services/java.nio.charset.spi.CharsetProvider
new file mode 100644
index 0000000..d29245f
--- /dev/null
+++ b/luni/src/test/resources/META-INF/services/java.nio.charset.spi.CharsetProvider
@@ -0,0 +1,2 @@
+tests.api.java.nio.charset.CharsetTest$MockCharsetProvider
+tests.api.java.nio.charset.CharsetTest$MockCharsetProviderASCII
diff --git a/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterface b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterface
index 8f8a9eb..2961ffb 100644
--- a/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterface
+++ b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterface
@@ -5,3 +5,4 @@
libcore.java.util.ServiceLoaderTest$Impl2 # this comment is valid
libcore.java.util.ServiceLoaderTest$Impl2#as is this
libcore.java.util.ServiceLoaderTest$Impl2 # and duplicates are allowed too
+ libcore.java.util.ServiceLoaderTest$Impl2 # as is leading whitespace
diff --git a/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceMissingClass b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceMissingClass
new file mode 100644
index 0000000..253a7b4
--- /dev/null
+++ b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceMissingClass
@@ -0,0 +1 @@
+this.class.does.not.Exist
diff --git a/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceParseError b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceParseError
new file mode 100644
index 0000000..8573996
--- /dev/null
+++ b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceParseError
@@ -0,0 +1 @@
+this is not a valid class name!
diff --git a/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceWrongType b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceWrongType
new file mode 100644
index 0000000..e8caaf3
--- /dev/null
+++ b/luni/src/test/resources/META-INF/services/libcore.java.util.ServiceLoaderTestInterfaceWrongType
@@ -0,0 +1 @@
+java.lang.String
diff --git a/luni/src/test/java/libcore/java/lang/ref/FinalizationTester.java b/support/src/test/java/libcore/java/lang/ref/FinalizationTester.java
similarity index 100%
rename from luni/src/test/java/libcore/java/lang/ref/FinalizationTester.java
rename to support/src/test/java/libcore/java/lang/ref/FinalizationTester.java